Skip to content

Instantly share code, notes, and snippets.

@comefrombottom
Created December 21, 2023 04:45
Show Gist options
  • Save comefrombottom/90ada0cd02a0b129d2f8d4ae7ed9b97a to your computer and use it in GitHub Desktop.
Save comefrombottom/90ada0cd02a0b129d2f8d4ae7ed9b97a to your computer and use it in GitHub Desktop.
Rayと変換座標が適応された図形との当たり判定
# 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