summaryrefslogtreecommitdiff
path: root/modules/csg/csg_shape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/csg/csg_shape.cpp')
-rw-r--r--modules/csg/csg_shape.cpp193
1 files changed, 154 insertions, 39 deletions
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 4e35014459..23725c4960 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 */
@@ -48,18 +48,76 @@ void CSGShape::set_use_collision(bool p_enable) {
PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
+ set_collision_layer(collision_layer);
+ set_collision_mask(collision_mask);
_make_dirty(); //force update
} else {
PhysicsServer::get_singleton()->free(root_collision_instance);
root_collision_instance = RID();
root_collision_shape.unref();
}
+ _change_notify();
}
bool CSGShape::is_using_collision() const {
return use_collision;
}
+void CSGShape::set_collision_layer(uint32_t p_layer) {
+ collision_layer = p_layer;
+ if (root_collision_instance.is_valid()) {
+ PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer);
+ }
+}
+
+uint32_t CSGShape::get_collision_layer() const {
+
+ return collision_layer;
+}
+
+void CSGShape::set_collision_mask(uint32_t p_mask) {
+
+ collision_mask = p_mask;
+ if (root_collision_instance.is_valid()) {
+ PhysicsServer::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask);
+ }
+}
+
+uint32_t CSGShape::get_collision_mask() const {
+
+ return collision_mask;
+}
+
+void CSGShape::set_collision_mask_bit(int p_bit, bool p_value) {
+
+ uint32_t mask = get_collision_mask();
+ if (p_value)
+ mask |= 1 << p_bit;
+ else
+ mask &= ~(1 << p_bit);
+ set_collision_mask(mask);
+}
+
+bool CSGShape::get_collision_mask_bit(int p_bit) const {
+
+ return get_collision_mask() & (1 << p_bit);
+}
+
+void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) {
+
+ uint32_t mask = get_collision_layer();
+ if (p_value)
+ mask |= 1 << p_bit;
+ else
+ mask &= ~(1 << p_bit);
+ set_collision_layer(mask);
+}
+
+bool CSGShape::get_collision_layer_bit(int p_bit) const {
+
+ return get_collision_layer() & (1 << p_bit);
+}
+
bool CSGShape::is_root_shape() const {
return !parent;
@@ -197,17 +255,6 @@ void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexc
fvTexcOut[1] = t.y;
}
-void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) {
- ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
-
- int i = (iFace * 3 + iVert) * 4;
-
- surface.tansw[i++] = fvTangent[0];
- surface.tansw[i++] = fvTangent[1];
- surface.tansw[i++] = fvTangent[2];
- surface.tansw[i++] = fSign;
-}
-
void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
@@ -216,7 +263,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f
int i = iFace * 3 + iVert;
Vector3 normal = surface.normalsw[i];
Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
- Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+ Vector3 bitangent = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot
float d = bitangent.dot(normal.cross(tangent));
i *= 4;
@@ -389,10 +436,10 @@ void CSGShape::_update_shape() {
}
// unset write access
- surfaces.write[i].verticesw = PoolVector<Vector3>::Write();
- surfaces.write[i].normalsw = PoolVector<Vector3>::Write();
- surfaces.write[i].uvsw = PoolVector<Vector2>::Write();
- surfaces.write[i].tansw = PoolVector<float>::Write();
+ surfaces.write[i].verticesw.release();
+ surfaces.write[i].normalsw.release();
+ surfaces.write[i].uvsw.release();
+ surfaces.write[i].tansw.release();
if (surfaces[i].last_added == 0)
continue;
@@ -470,6 +517,8 @@ void CSGShape::_notification(int p_what) {
PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
+ set_collision_layer(collision_layer);
+ set_collision_mask(collision_mask);
}
_make_dirty();
@@ -482,13 +531,20 @@ void CSGShape::_notification(int p_what) {
}
}
+ if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+
+ if (parent) {
+ parent->_make_dirty();
+ }
+ }
+
if (p_what == NOTIFICATION_EXIT_TREE) {
if (parent)
parent->_make_dirty();
parent = NULL;
- if (use_collision && is_root_shape()) {
+ if (use_collision && is_root_shape() && root_collision_instance.is_valid()) {
PhysicsServer::get_singleton()->free(root_collision_instance);
root_collision_instance = RID();
root_collision_shape.unref();
@@ -501,6 +557,7 @@ void CSGShape::set_operation(Operation p_operation) {
operation = p_operation;
_make_dirty();
+ update_gizmo();
}
CSGShape::Operation CSGShape::get_operation() const {
@@ -517,12 +574,27 @@ bool CSGShape::is_calculating_tangents() const {
}
void CSGShape::_validate_property(PropertyInfo &property) const {
- if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) {
+ bool is_collision_prefixed = property.name.begins_with("collision_");
+ if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) {
//hide collision if not root
property.usage = PROPERTY_USAGE_NOEDITOR;
+ } else if (is_collision_prefixed && !bool(get("use_collision"))) {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
+Array CSGShape::get_meshes() const {
+
+ if (root_mesh.is_valid()) {
+ Array arr;
+ arr.resize(2);
+ arr[0] = Transform();
+ arr[1] = root_mesh;
+ return arr;
+ }
+
+ return Array();
+}
void CSGShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape::_update_shape);
@@ -531,34 +603,54 @@ void CSGShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape::set_operation);
ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_operation);
+ ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
+ ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
+
ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape::set_use_collision);
ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape::is_using_collision);
- ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
- ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
+ ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer);
+ ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape::get_collision_layer);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape::get_collision_mask_bit);
+
+ ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape::set_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape::get_collision_layer_bit);
ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents);
ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents);
+ ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape::get_meshes);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents");
+ ADD_GROUP("Collision", "collision_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+
BIND_ENUM_CONSTANT(OPERATION_UNION);
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION);
}
CSGShape::CSGShape() {
+ operation = OPERATION_UNION;
+ parent = NULL;
brush = NULL;
- set_notify_local_transform(true);
dirty = false;
- parent = NULL;
- use_collision = false;
- operation = OPERATION_UNION;
snap = 0.001;
+ use_collision = false;
+ collision_layer = 1;
+ collision_mask = 1;
calculate_tangents = true;
+ set_notify_local_transform(true);
}
CSGShape::~CSGShape() {
@@ -633,6 +725,7 @@ CSGBrush *CSGMesh::_build_brush() {
PoolVector<bool> smooth;
PoolVector<Ref<Material> > materials;
PoolVector<Vector2> uvs;
+ Ref<Material> material = get_material();
for (int i = 0; i < mesh->get_surface_count(); i++) {
@@ -669,7 +762,12 @@ CSGBrush *CSGMesh::_build_brush() {
uvr_used = true;
}
- Ref<Material> mat = mesh->surface_get_material(i);
+ Ref<Material> mat;
+ if (material.is_valid()) {
+ mat = material;
+ } else {
+ mat = mesh->surface_get_material(i);
+ }
PoolVector<int> aindices = arrays[Mesh::ARRAY_INDEX];
if (aindices.size()) {
@@ -715,8 +813,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
} else {
int as = vertices.size();
@@ -758,8 +856,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
}
}
@@ -775,6 +873,18 @@ void CSGMesh::_mesh_changed() {
update_gizmo();
}
+void CSGMesh::set_material(const Ref<Material> &p_material) {
+ if (material == p_material)
+ return;
+ material = p_material;
+ _make_dirty();
+}
+
+Ref<Material> CSGMesh::get_material() const {
+
+ return material;
+}
+
void CSGMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh::set_mesh);
@@ -782,7 +892,11 @@ void CSGMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("_mesh_changed"), &CSGMesh::_mesh_changed);
+ ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh::set_material);
+ ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh::get_material);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material");
}
void CSGMesh::set_mesh(const Ref<Mesh> &p_mesh) {
@@ -1062,9 +1176,9 @@ CSGBrush *CSGBox::_build_brush() {
for (int k = 0; k < 3; k++) {
if (i < 3)
- face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[j][(i + k) % 3] = v[k];
else
- face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[3 - j][(i + k) % 3] = -v[k];
}
}
@@ -1703,11 +1817,9 @@ CSGBrush *CSGPolygon::_build_brush() {
path_cache = path;
- if (path_cache) {
- path_cache->connect("tree_exited", this, "_path_exited");
- path_cache->connect("curve_changed", this, "_path_changed");
- path_cache = NULL;
- }
+ path_cache->connect("tree_exited", this, "_path_exited");
+ path_cache->connect("curve_changed", this, "_path_changed");
+ path_cache = NULL;
}
curve = path->get_curve();
if (curve.is_null())
@@ -1969,6 +2081,9 @@ CSGBrush *CSGPolygon::_build_brush() {
for (int i = 0; i <= splits; i++) {
float ofs = i * path_interval;
+ if (ofs > bl) {
+ ofs = bl;
+ }
if (i == splits && path_joined) {
ofs = 0.0;
}