Нормаль для нормали или касательная плоскость в точке

Версия Minecraft
0.1+
1,976
68
220
Доброго времени суток о/

Дело было вечером, делать было нечего, собрались как-то Сокол, Сыч, Джаст и Дахака и попытались вспомнить школьный курс стереометрии, а именно как же найти любой перпендикуляр к нормали в Декартовых координатах. Думали час, думали другой, да так ничего и не придумали.

Суть задачи в следующем:
Дана сферическая система координат, а именно радиус r и углы, зенитный и азимутальный (pitch и yaw). Нужно создать сферу (на частицах), точки которой будут двигаться в случайном направлении в пределах касательной плоскости.
Начинаем с перевода из Сферической системы в Декартову, используя эти формулы:
ff18b6086ad611568d8dc6656715a29e0f76c540

Ура-ура, у нас есть вполне себе сфера, состоящая из точек (партиклов).
ivfZVd4cfTM.jpg

Коли кому-то не видно...
dPZ9DBSr0D0.jpg
А теперь задача - рассчитать движение этих партиклов по любой из касательных в соответствующей точке.
Вроде всё просто - всего-то найти любую касательную и пустить по ней частицы. Однако четыре взрослых дяди в сумме потратили на это три часа, а в итоге ничего.

Вот, собственно, кусок кода:
Java:
    @SubscribeEvent
    @SideOnly(Side.CLIENT)
    public void onWorldLastRender(RenderWorldLastEvent e) {
        float range = 12;
        int mod = 10;
        ChunkCoordinates source = new ChunkCoordinates(0, 100, 0);
        for(int pitch = 0; pitch <= 180; pitch += mod)
            for(int yaw = 0; yaw < 360; yaw += mod) {
                // Цвет
                float r = 0.5F;
                float g = 0F;
                float b = 1F;
    
                // Угол в радианах
                float radY = yaw * (float) Math.PI / 180F;
                float radP = pitch * (float) Math.PI / 180F;
                
                // Мировые координаты
                double X = source.posX + 0.5;
                double Y = source.posY + 0.5;
                double Z = source.posZ + 0.5;
                
                // Локальные координаты (Сфер. сис. -> Декарт сис.)
                double x = Math.sin(radP) * Math.cos(radY) * range;
                double y = Math.cos(radP) * range;
                double z = Math.sin(radP) * Math.sin(radY) * range;
                
                // Движение - надо найти.
                float motX = 0F;
                float motY = 0F;
                float motZ = 0F;
    
                // Спаун партикла
                // World world, double x, double y, double z, float r, float g, float b, float size, float motionx, float motiony, float motionz
                Botania.proxy.wispFX(Minecraft.getMinecraft().theWorld, X-x, Y-y, Z-z, r, g, b, 1F, (float) (Math.random() - 0.5F) * motX, (float) (Math.random() - 0.5F) * motY, (float) (Math.random() - 0.5F) * motZ);
            }
    }
Надеюсь хоть кто-то не прогуливал школу и поможет с этим :D
Заранее спасибо
 
Решение
2 варианта:
1) У тебя есть 2 угла. Прибавь ка к одному из них 90 градусов и получишь перпендикуляр, при том весьма нормализованый. Если начнешь изменять 2ой угол, вектор все еще останется перепендикуляром. Вот как бы и долбись с этим.
2) Так как тебе нужно, на сколько я понял, весьма хаотичное движение возьми текущие углы и добавь к ним немного, ну и найди по ним новую точку. Profit!
1,111
47
420
2 варианта:
1) У тебя есть 2 угла. Прибавь ка к одному из них 90 градусов и получишь перпендикуляр, при том весьма нормализованый. Если начнешь изменять 2ой угол, вектор все еще останется перепендикуляром. Вот как бы и долбись с этим.
2) Так как тебе нужно, на сколько я понял, весьма хаотичное движение возьми текущие углы и добавь к ним немного, ну и найди по ним новую точку. Profit!
 
7,099
324
1,509
Логика такая: имея точку на сфере и центр сферы можно получить нормаль плоскости. После этого выбираем рандомный угол и на этот угол вращаем вектор, исходящий из точки на сфере и перпендикулярный нормали. Полученный вектор будет направлением движения.
---
Может, чуть позже запишу формульно и кодом
 
1,111
47
420
1. А как его сдвинуть потом?
D83EDD14.png
Зачем тебе его сдвигать? Возьми да и прибавь его к xyz партикла. Задачу поиска перпендикуляра к нормали этот способ решает.

2. Нет, точки менять нельзя, нужны аки источники, распыляющие партиклы.
Ты шо долбишься что ли? Какие еще "источники, распыляющие партиклы"!?
 
1,976
68
220
1) У тебя есть 2 угла. Прибавь ка к одному из них 90 градусов и получишь перпендикуляр, при том весьма нормализованый. Если начнешь изменять 2ой угол, вектор все еще останется перепендикуляром. Вот как бы и долбись с этим.
Хе... хе-хе... хехех... Мать твою за ногу, дядя, а какого хрена, спрашивается, ты этого раньше не скинул? Аргх!
Во всяком случае похоже на правду.

Правда чем ближе к верхней/нижней точке, тем кривее оно работает, но так, вроде, всё шикарно.
 
Сверху