Created
December 21, 2023 04:45
-
-
Save comefrombottom/90ada0cd02a0b129d2f8d4ae7ed9b97a to your computer and use it in GitHub Desktop.
Rayと変換座標が適応された図形との当たり判定
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# include <Siv3D.hpp> // Siv3D v0.6.12 | |
Ray transformedRay(const Ray& ray, const Mat4x4& mat) { | |
return Ray(mat.transformPoint(ray.getOrigin()), mat.transformPoint(ray.getDirection()).withLength(1)); | |
} | |
struct HexFace { | |
static Vec3 getFaceNormal(uint8 i) { | |
static std::array<Vec3, 6> normals{ | |
Vec3{-1, 0, 0}, | |
Vec3{ 0,-1,0 }, | |
Vec3{ 0,0,-1 }, | |
Vec3{ 1,0,0 }, | |
Vec3{ 0,1,0 }, | |
Vec3{ 0,0,1 } | |
}; | |
return normals[i]; | |
} | |
Optional<std::pair<uint8, double>> intersects(const Ray& ray) { | |
double min = Math::Inf; | |
uint8 faceNum; | |
for (auto i : step(6)) { | |
Mat4x4 mat(Quaternion::FromUnitVectors({ 0,1,0 }, getFaceNormal(i))); | |
if (auto distance = Plane({ 0,0.5,0 }, 1).intersects(transformedRay(ray, mat.inverse()))) { | |
if (*distance < min) { | |
min = *distance; | |
faceNum = i; | |
} | |
} | |
} | |
if (not IsInfinity(min)) { | |
return { {faceNum,min} }; | |
} | |
return none; | |
} | |
void draw()const { | |
Box(1).draw(); | |
} | |
void draw(uint8 faceNum)const { | |
Box(1).draw(); | |
Mat4x4 mat(Quaternion::FromUnitVectors({ 0,1,0 }, getFaceNormal(faceNum))); | |
Transformer3D tf{ mat }; | |
Plane({ 0,0.51,0 }, 1).draw(Linear::Palette::Pink); | |
} | |
}; | |
void Main() | |
{ | |
const ColorF backgroundColor = ColorF{ 0.4, 0.6, 0.8 }.removeSRGBCurve(); | |
const MSRenderTexture renderTexture{ Scene::Size(), TextureFormat::R8G8B8A8_Unorm_SRGB, HasDepth::Yes }; | |
HexFace hexFace; | |
BasicCamera3D camera{ renderTexture.size(),30_deg,{0,0,-10} }; | |
Quaternion quaternion = Quaternion::Identity(); | |
while (System::Update()) | |
{ | |
ClearPrint(); | |
if (MouseL.pressed()) { | |
if (not Cursor::DeltaF().isZero()) { | |
quaternion *= Quaternion::RotationNormal({ Cursor::DeltaF().yx().normalized(),0 }, -Cursor::DeltaF().length() / 200); | |
} | |
} | |
if (MouseR.pressed()) { | |
quaternion *= Quaternion::RotationNormal({ 0,0,1 }, -(Cursor::PosF() - Scene::CenterF()).normalized().cross(Cursor::DeltaF()) / 200); | |
} | |
Graphics3D::SetCameraTransform(camera); | |
{ | |
const ScopedRenderTarget3D target{ renderTexture.clear(backgroundColor) }; | |
Transformer3D tf{ Mat4x4(quaternion) }; | |
Ray ray = camera.screenToRay(Cursor::PosF()); | |
if (auto opt = hexFace.intersects(transformedRay(ray,Graphics3D::GetLocalTransform().inverse()))) { | |
auto& [index, dist] = *opt; | |
hexFace.draw(index); | |
} | |
else { | |
hexFace.draw(); | |
} | |
} | |
Graphics3D::Flush(); | |
renderTexture.resolve(); | |
Shader::LinearToScreen(renderTexture); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment