Темы:
Предисловие
В моей небольшой практике LSL-программирования иногда возникали спонтанные задачки, которые я начинал было решать, но после забрасывал, так как они переставали быть мне интересны. Именно о них я и хочу вам рассказать. Все эти идеи так и не получили окончательного воплощения. Так что, дорогие читатели, если они покажутся интересными и вам, можете попробовать довести их до победного конца самостоятельно, повысив тем самым свой уровень владения технологией программирования LSL.
Первая идея, которую я представляю вашему вниманию - железная дорога, или движение объекта по заданному пути.
Мысль об этом пришла мне в голову после катания по трассе Visboo. Уже с первых минут стало ясно - нормально поездить не удастся - скорость моего соединения с Интернетом приводила к тому, что машина почти все время проваливалась сквозь трассу. Было бы здорово, если бы что-то удерживало ее от этого, подумалось мне. Например, она могла бы "лететь" по заранее проложенной трассе без моего участия - это показалось мне гораздо лучше того, что я наблюдал в действительности.
Итак, смысл задачи сводился к организации движения некоторого объекта по заранее заданному пути в пределах одного сима. Как это сделать быстро и красиво?
Описание пути
Если путь, то есть дорога или набор точек (поинтов), между которыми нужно двигаться по некоторым кривым, уже существует, то все просто.

Вид дороги в графическом редакторе Surpac с включенной трехмерной сеткой - нажмите на изображение для увеличения
Создаем специальный скрипт-трекер с неким примом, например, пирамидкой. "Цепляем" на себя (wear) трекер и летим (идем) с ним по точкам нашего пути. Трекер "снимает" эти точки и пишет их в чат. По окончании записи всех точек вам необходимо скопировать их из хистори в текстовый файл. Назовем его points1.txt.
Получим обычные тройки координат с разделителем ";" - "X,Y,Z;".

Результат работы трекера: набор точек до сжатия - кликните на изображение для увеличения
Наверно, вы подумали, что это будет заметка (notecard) для движения нашего объекта? Нет, пока это всего лишь полуфабрикат. Нам предстоит его обработать, чтобы сократить объем информации, ведь чтение такой заметки средствами LSL может длиться довольно долго - до нескольких минут.
Лучше всего считать всю заметку в память скрипта, а потом уже с ней работать. Поскольку объем памяти скрипта ограничен, лучше всего считывать данные в том же виде, в каком они хранятся в упакованной заметке - одной длинной строкой.
Упаковка точек "в хлам"
Для преобразования точек из векторного вида в упакованный применим внешнюю программу на Delphi (см. листинг MainUnit.pas).
Принцип упаковки: 255.5,255.5,768.9, 6 символов - по 2 на каждую координату.
Ограничения: x,y = 1..2550 (точность 0.1), z = 1..7000 (точность 0.1).
Символ: 32..127 = 95 вариантов, 95*95 = 9025 – нормально, значит, одно число "упаковываем" в 2 символа.
Формат карты: символы идут спошь по 252 в строку, каждые 6 символов – одна точка. Итого, в 252 символа укладываем 42 точки. Скрипт читает путь сразу весь в одну очень длинную строку с использованием секрета:
way = (way="") + way + data.
Преобразование координаты вида NNN.N в два символа (#32..#127):
h:=round(coo[j]*10); c1:=h div base; c2:=h mod base;
s:=s+chr(32+c1)+chr(32+c2).
Логически: целое число вида NNNN пишется в два символа по модулю 95.
Затем в LSL сборка числа из двух символов выполняется по обратной формуле вида:
r = ((ord(c1) - 32 ) * 95 + (ord(c2) - 32 ))/10.0

Функция GetPoint - кликните на изображение для увеличения
В LSL пишем функцию GetPoint – взятие вектора по индексу из длинной строки way (см. листинг wc_rail.lsl).
Выравнивание и исправление ошибок
То, что я рассказывал выше про трекер и про точки – это, конечно, идеальный случай. В реальности дела обстоят совсем по-другому. Я шел по ж/д путям на TechInvestlab и упал с моста. И трекер записал всю дугу падения и возврата моего аватара на мост в мельчайших подробностях. Что в таком случае делать? Необходим анализ снятых точек!

Фрагмент дороги с отображением номеров точек - нажмите на изображение для увеличения
Для трехмерных анализов я всегда использую демоверсию Surpac, скачать которую можно здесь. Вы можете попробовать что-нибудь другое. Главное в нашем случае – увидеть путь, покрутить, найти лишние вершины, удалить их и скорректировать неровности. Ручная корректировка выполняется следующим образом: в 3D-вьюере вы замечаете, какие точки выбиваются из графика, находите их в points1.txt и исправляете.
Разрядка точек
В предложенном листинге Delphi имеется процедура "Condense", применяемая при ручном вводе точек с целью уменьшения числа вершин на ломаной линии.
В результате ее выполнения количество вершин линии уменьшается следующим образом:
- вершины, расстояние между которыми меньше e1, переходят в одну;
- если три последовательные вершины линии лежат на одной прямой с точностью до e2, то промежуточная вершина удаляется.

Уменьшение количества вершин
С применением операции разрядки число точек файла points1.txt уменьшилось на 30%.
Полет аппарата
Теперь несколько слов о том, как работает наш летательный аппарат.
- По команде "readway" он читает заметку пути "way" целиком в память скрипта (в одну строку).
- Переходит на первую точку (SetPos()).
- Движется по следующим точкам согласно формуле k = (k + sign) % n, где n – число точек, sign – знак движения (+1/-1 – вперед/назад).
- При движении ось аппарата поворачивается в пространстве в соответствии с углом поворота текущего ребра.

Cranyak в туннеле
Ну, а дальше вы можете развивать предложенный алгоритм, используя всю вашу фантазию.
Что я упустил, и что вы можете доделать
Во-первых, скрипт LSL-полета не учитывает расстояний между соседними точками пути и движется каждую секунду ровно на одно ребро независимо от его длины.
Во-вторых, LSL-трекер для снятия точек пути можно сделать и получше, например, включить туда алгоритм разрядки точек.
В-третьих, более изящным было бы движение по параметрической кубической кривой.
Приложения
Исходный текст LSL-трекера - pnt_scan.lsl.
Снятый трекером путь - points1.txt.
Код программы обработки пути на Delphi - MainUnit.pas
Весь проект Delphi с исходными текстами - delphi_src.zip.
Стринг ж/д пути для просмотра в Surpac - investlab.txt.str.
Упакованная "в хлам" заметка с ж/д путем - investlab.txt.note
Исходный код LSL-скрипта полета - wc_rail.lsl.
Рисунки

Исходный код программы-трекера - нажмите на изображение для увеличения

Delphi: Описание типов и переменных - нажмите на изображение для увеличения

Процедура split на языке Delphi - нажмите на изображение для увеличения

Delphi: Процедура перевода файла точек в заметку (а также в стринг Surpac для анализа) - нажмите на изображение для увеличения

Результат сжатия - заметка из точек, упакованных "в хлам" - нажмите на изображение для увеличения
![]()
Размер заметки после сжатия предложенным алгоритмом - 2 килобайта вместо 11

LSL: Исходный код программы полета по точкам. Начало - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Состояние default - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Состояние setup - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Командный процессор, стр. 1 - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Командный процессор, стр. 2 - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Функция извлечения точки из 6-символьной подстроки в вектор - нажмите на изображение для увеличения

LSL: Исходный код программы полета по точкам. Функция UTF8ToUnicodeInteger - нажмите на изображение для увеличения
|
Cranyak Homewood 12:31, 08.08.07 ссылка
Читал сейчас свою статью на сайте, насчитал 5 орфографических ошибок в тексте. :( Список: Хорошо бы их исправили, а то подумают, что я эту статью _так_ написал. Ответить |
|
milas 12:34, 08.08.07 ссылка
Большое спасибо за оперативные замечания! Исправления будут внесены немедленно. Ответить |
|
Ivus 02:11, 09.08.07 ссылка
А сама статья - замечательная. Побольше таких авторов и статей! |
|
Cranyak Homewood 22:54, 16.08.07 ссылка
Спасибо, Ивус! У этой статьи скоро будет продолжение... Ответить |
|
Alex 04:13, 17.08.07 ссылка
SetPos выполняет Critical Dump к точке (рывок с постепенно убывающей скоростью) - это не полёт, прыгание рывками. Вы динамикой (в физике) попробуйте сделайте... Там уже сплайнами не обойдетесь, надо уравнение движения решать для того, чтобы даже места для точек расставить. Но все это можно сделать. Мы сделали. Можете сходить полетать. Adscita. Ответить |
|
Mikhail Troncon 12:22, 30.01.08 ссылка
У меня программа pnts2note выдает ошибку Error Filename, после нажатия на кнопку расчет. к сожалению не разбираюсь в паскале, чтобы править исходники Ответить |
















