Enhance | 实现了一部分编辑器内碰撞箱检测

This commit is contained in:
shenjack 2023-12-22 23:30:56 +08:00
parent 0e1d260bb2
commit 549f85f673
Signed by: shenjack
GPG Key ID: 7B1134A979775551
6 changed files with 157 additions and 25 deletions

View File

@ -9,3 +9,5 @@
pub mod dr;
pub mod math;
pub mod sr1;
pub type IdType = i128;

View File

@ -1,8 +1,8 @@
use std::collections::HashMap;
use nalgebra::Vector2;
use rapier2d_f64::geometry::{SharedShape, TriMeshFlags};
use rapier2d_f64::math::{Isometry, Point, Real};
use rapier2d_f64::geometry::TriMeshFlags;
use rapier2d_f64::math::{Point, Real};
use rapier2d_f64::parry::transformation::vhacd::VHACDParameters;
pub enum ConnectType {

View File

@ -13,8 +13,8 @@ use crate::sr1_data::ship::{
};
use crate::data_type::math::{Point2D, Rotatable};
use crate::data_type::IdType;
pub type IdType = i64;
pub type ConnectionType = Vec<(Vec<SR1PartData>, Option<Vec<Connection>>)>;
pub fn radians_map_to_degrees(angle: f64) -> f64 {

View File

@ -4,9 +4,10 @@ use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use crate::data_type::math::{Point2D, Rotatable};
use crate::data_type::sr1::SaveStatus;
use crate::data_type::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
use crate::data_type::sr1::{IdType, SaveStatus};
use crate::data_type::sr1::{SR1PartList, SR1PartType, SR1Ship};
use crate::data_type::IdType;
use crate::sr1_data::part_list::RawPartList;
#[pyclass]
@ -308,10 +309,10 @@ impl PySR1Ship {
parts
}
fn get_part_box(&self, part_id: i64) -> Option<((f64, f64), (f64, f64))> {
fn get_part_box(&self, part_id: IdType) -> Option<((f64, f64), (f64, f64))> {
let part_data = self.ship.parts.iter().find(|&x| x.id == part_id);
if let Some(part_data) = part_data {
let part_type = self.part_list.get_part_type(&part_data.part_type_id).unwrap();
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
// rotate
let radius = part_data.angle;
let ((x1, y1), (x2, y2)) = part_type.get_box();
@ -324,6 +325,7 @@ impl PySR1Ship {
p2.add_mut(part_data.x * 2.0, part_data.y * 2.0);
return Some(((p1.x, p1.y), (p2.x, p2.y)));
}
}
None
}

View File

@ -6,14 +6,141 @@
* -------------------------------
*/
use nalgebra::Vector2;
use nalgebra::{Matrix2, Vector2};
use pyo3::prelude::*;
use rapier2d_f64::math::Real;
use crate::data_type::dr::BoxColliderEnum;
use crate::data_type::IdType;
/// Id 位置 碰撞体
pub type BoundedShape = (IdType, Vector2<Real>, EditorShapeEnum);
pub enum EditorShapeEnum {
/// 矩形
/// 一个方向的向量 另一个方向的向量
Cuboid(Vector2<Real>, Vector2<Real>),
/// 三角形
/// 一个方向的向量 另一个方向的向量
Triangle(Vector2<Real>, Vector2<Real>),
/// 圆
/// 半径
Ball(Real),
/// 组合
Compound(Vec<EditorShapeEnum>),
}
// #[pyclass]
pub struct EditorArea {
/// 存储所有碰撞箱信息
pub collision_box: Vec<BoxColliderEnum>,
pub collision_box: Vec<BoundedShape>,
}
impl EditorArea {
/// 添加一个碰撞箱
pub fn add_box(&mut self, box_data: BoundedShape) {
self.collision_box.push(box_data);
}
/// 删除一个碰撞箱
pub fn remove_box_by_id(&mut self, id: IdType) -> bool {
for (i, box_data) in self.collision_box.iter().enumerate() {
if box_data.0 == id {
self.collision_box.remove(i);
return true;
}
}
false
}
/// 检查一个点是否碰撞到任意一个碰撞箱
pub fn check_hit(&self, point: Vector2<Real>) -> Option<IdType> {
for box_data in self.collision_box.iter() {
match &box_data.2 {
// 球 直接勾股定理秒了
EditorShapeEnum::Ball(r) => {
if (point - box_data.1).norm() <= *r {
return Some(box_data.0);
}
}
// 矩形
// 进行一个旋转
EditorShapeEnum::Cuboid(dir1, dir2) => {
// 先平移坐标系
let point = point - box_data.1;
// 求出逆矩阵
let inv = Matrix2::new(dir1.x, dir2.x, dir1.y, dir2.y).try_inverse().unwrap();
// 变换
let point = inv * point;
// 判断是否在矩形内
if point.x >= 0.0 && point.x <= 1.0 && point.y >= 0.0 && point.y <= 1.0 {
return Some(box_data.0);
} else {
continue;
}
},
// 三角形
EditorShapeEnum::Triangle(dir1, dir2) => {
// 先平移坐标系
let point = point - box_data.1;
// 求出逆矩阵
let inv = Matrix2::new(dir1.x, dir2.x, dir1.y, dir2.y).try_inverse().unwrap();
// 变换
let point = inv * point;
// 判断是否在三角形内
if point.x >= 0.0 && point.y >= 0.0 && point.x + point.y <= 1.0 {
return Some(box_data.0);
} else {
continue;
}
},
EditorShapeEnum::Compound(shapes) => {
for shape in shapes {
match shape {
// 球 直接勾股定理秒了
EditorShapeEnum::Ball(r) => {
if (point - box_data.1).norm() <= *r {
return Some(box_data.0);
}
}
// 矩形
// 进行一个旋转
EditorShapeEnum::Cuboid(dir1, dir2) => {
// 先平移坐标系
let point = point - box_data.1;
// 求出逆矩阵
let inv = Matrix2::new(dir1.x, dir2.x, dir1.y, dir2.y).try_inverse().unwrap();
// 变换
let point = inv * point;
// 判断是否在矩形内
if point.x >= 0.0 && point.x <= 1.0 && point.y >= 0.0 && point.y <= 1.0 {
return Some(box_data.0);
} else {
continue;
}
},
// 三角形
EditorShapeEnum::Triangle(dir1, dir2) => {
// 先平移坐标系
let point = point - box_data.1;
// 求出逆矩阵
let inv = Matrix2::new(dir1.x, dir2.x, dir1.y, dir2.y).try_inverse().unwrap();
// 变换
let point = inv * point;
// 判断是否在三角形内
if point.x >= 0.0 && point.y >= 0.0 && point.x + point.y <= 1.0 {
return Some(box_data.0);
} else {
continue;
}
},
EditorShapeEnum::Compound(_) => {
panic!("Compound in Compound");
},
}
}
}
}
}
None
}
}

View File

@ -6,8 +6,9 @@ use serde::{Deserialize, Serialize};
use serde_xml_rs::from_str;
use serde_xml_rs::Error as XmlError;
use crate::data_type::sr1::{IdType, SR1PartData, SR1PartDataAttr, SR1Ship};
use crate::data_type::sr1::{SR1PartData, SR1PartDataAttr, SR1Ship};
use crate::data_type::sr1::{SR1PartDataTrait, SR1ShipTrait};
use crate::data_type::IdType;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename = "Ship")]
@ -51,7 +52,7 @@ pub struct Part {
pub pod: Option<Pod>,
#[serde(rename = "partType")]
pub part_type_id: String,
pub id: i64,
pub id: IdType,
pub x: f64,
pub y: f64,
#[serde(rename = "editorAngle")]
@ -119,7 +120,7 @@ pub struct Step {
#[serde(rename = "Activate")]
pub struct Activate {
#[serde(rename = "Id")]
pub id: i64,
pub id: IdType,
pub moved: i8, // 1 or 0
}