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

Версия Minecraft
0.1+
1,978
67
196
Доброго времени суток о/

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

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

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

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

Вот, собственно, кусок кода:
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) Так как...
1,064
47
381
2 варианта:
1) У тебя есть 2 угла. Прибавь ка к одному из них 90 градусов и получишь перпендикуляр, при том весьма нормализованый. Если начнешь изменять 2ой угол, вектор все еще останется перепендикуляром. Вот как бы и долбись с этим.
2) Так как тебе нужно, на сколько я понял, весьма хаотичное движение возьми текущие углы и добавь к ним немного, ну и найди по ним новую точку. Profit!
 
Решение
5,397
179
984
Логика такая: имея точку на сфере и центр сферы можно получить нормаль плоскости. После этого выбираем рандомный угол и на этот угол вращаем вектор, исходящий из точки на сфере и перпендикулярный нормали. Полученный вектор будет направлением движения.
---
Может, чуть позже запишу формульно и кодом
 
1,064
47
381
1. А как его сдвинуть потом?
Зачем тебе его сдвигать? Возьми да и прибавь его к xyz партикла. Задачу поиска перпендикуляра к нормали этот способ решает.

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

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