Enhance | 实现了一部分编辑器内碰撞箱检测
This commit is contained in:
parent
0e1d260bb2
commit
549f85f673
@ -9,3 +9,5 @@
|
||||
pub mod dr;
|
||||
pub mod math;
|
||||
pub mod sr1;
|
||||
|
||||
pub type IdType = i128;
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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,21 +309,22 @@ 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();
|
||||
// rotate
|
||||
let radius = part_data.angle;
|
||||
let ((x1, y1), (x2, y2)) = part_type.get_box();
|
||||
let mut p1 = Point2D::new(x1, y1);
|
||||
let mut p2 = Point2D::new(x2, y2);
|
||||
p1.rotate_radius_mut(radius);
|
||||
p2.rotate_radius_mut(radius);
|
||||
// transform
|
||||
p1.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
p2.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
return Some(((p1.x, p1.y), (p2.x, p2.y)));
|
||||
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();
|
||||
let mut p1 = Point2D::new(x1, y1);
|
||||
let mut p2 = Point2D::new(x2, y2);
|
||||
p1.rotate_radius_mut(radius);
|
||||
p2.rotate_radius_mut(radius);
|
||||
// transform
|
||||
p1.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
p2.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||
return Some(((p1.x, p1.y), (p2.x, p2.y)));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user