Язык программирования

Раздел модуля start

В языке программирования существует специальный раздел start, предназначенный для выполнения инициализационного кода перед циклом формирования кадров (код, вне раздела start исполняется при формировании каждого кадра). Обычно в разделе start объявляют и настраивают глобальные переменные, формируют параметры начальной стадии анимации. В разделе start нельзя описывать фигуры и модели из них. Однако, в разделе start обязательно необходимо включать модули, содержащие инициализационный код, причем без параметров, с индексами, которые используются при покадровом использовании. Также в разделе start описывают параметры сцены. В теле модуля может быть несколько разделов start или не одного.

Пример:
start {
<инициализационный код>
}
<покадровый код>


Типы переменных

int – целое 32 бита
dbl – вещественное двойной точности 64 бита
vec - вектор, запись содержащая вещественные поля типа dbl – (x,y,z)
log – логический тип, значения true и false
chr - символьный тип данных



Декларация переменных

Переменные в языке программирования делятся на 2 вида – локальные и глобальные. Глобальные обычно объявляются и настраиваются в разделе start и далее используются в вычислениях в каждом кадре, предназначены для обозначения стадии анимации. Локальные переменные объявлявляются и используются для локальных расчетов и уничтожаюся после выполнения кода, в котором были объявлены.

Декларация переменной имеет следующую структуру:
<обозначение типа переменной> <имя переменной> [=<выражение соответствующего типа>]

<обозначение типа переменной>:
- int, dbl, vec, log, chr – для локальных переменных
- gint, gdbl, gvec, glog, gchr – для глобальных переменных

<имя переменной> -строка из латинских символов или цифр, начинается с букв. Имя переменной не должно совпадать со служебными словами. Имя переменной не должно объявляться несколько раз в одном модуле, будь то локальная или глобальная переменная.

<Выражение соответствующего типа> - объявление переменной можно совместить с оператором присвоения. В выражении, значение которого присваивается переменной, не должна использоваться объявляемая переменная.

Помимо декларации отдельных переменных, можно объявить переменные – массивы из значений любого типа. Объявление выглядит так:
<тип> <имя>”[ ]” [<=выражение типа массив>]

Отличие от обычного объявления только в том, что после имени нужно указать квадратные скобки.
Индексация массива начинается от 0. Массивы являются динамическими. Их размер можно задать во время исполнения программы (явным или неявным образом).



Оператор присвоения

<Имя переменной> = <выражение соответствующего типа>

В качестве самостоятельной переменной, которой присваивается значение выражения, может выступать координата вектора, которая обозначается так: v.x, v.y, v.z. Такое обозначение можно использовать во всех конструкциях языка, за исключением объявления (объявить координату вектора отдельно нельзя, только вектор целиком).

Пример:
start {
gint i=0
}
dbl a
a=i*10
vec v=(0,-1,0)
v.x =v.y-a
chr c="@"
log b=(a=0)

Пример неправильного объявления:
start {
dbl d
}
vec v=v+v
dbl a.x=d

  1. В блоке start объявлять локальные переменные имеет смысл, только если они используются в блоке start (причем несколько раз как элемент выражения), после его обработки локальные переменные уничтожаются.
  2. В присваиваемом выражении нельзя использовать объявляемые переменные
  3. В объявлении нельзя использовать координаты векторов, только вектора целиком.

Примечание:
- Переменные объявленные в модуле относятся только к своему модулю. Вложенные модули могут содержать переменные, в т.ч. глобальные, у которых такие же имена.
- В качестве переменной, в которую можно присвоить значение может выступать массив целиком, отдельный элемент массива любого типа. При обращении к элементу массива, после имени массива в квадратных скобках указывается индекс элемента. Если при обращении к элементу указан индекс выходящий за пределы массива, компилятор выдает ошибку. Если при присвоении значения элементу массива указан индекс выходящий за пределы массива, то компилятор автоматически выделяет необходимый объем памяти (с копированием)

Пример:
dbl a[ ] = (0.5, 1.5, 2.5) // объявление и инициализация массива значениями3мя
a[3] = 3.5 // присвоение в 3-й элемент массива значения, длина увеличится сама!
vec b[] = ( (a[0],a[1],a[2]), (-1,0,0) ) // объявление и инициализация массива 2мя значениями
b[0].x=b[1].y +0.5 // присвоение значения координате вектора 0-го элемента массива
a=a+b+5 // настройка длины массива
chr ca[]="super3d" // присвоение значений в массив символов - (строковый тип)

Примечание:
Обратите внимание, что указание имени массива без квадратных скобок в выражении означает длину массива. Если с левой стороны оператора присвоения указано только имя массива (без []), то это означает настройку длины массива, при этом происходит перевыделение памяти, сопровождающееся копированием данных из прежнего массива.



Выражения и операции

Выражения представляют собой комбинацию операций с переменными или непосредственными значениями. Тип выражения должен быть таким же, что и переменная которой присваивается значение выражения. Исключение – выражение типа int и dbl, их значения можно присвоить как целой, так и вещественной переменной. Присваивая значение целой переменной, дробная часть значения выражения удаляется.

В выражениях численных типов (int, dbl) используются следующие операции:
+ , -, *, / - сложение, вычитание, умножение, деление. Причем умножение и деление имеет высший приоритет перед сложением и вычитанием, изменить приоритет можно с помощью скобок, например (a+b)*c = a*c + b*c, a+b*c = a+b*c, в качестве операндов могут выступать значения, переменные,функции, другие выражения.
Эти операции также допустимы с обозначениями длины массивов.

В выражениях векторного типа используются следующие операции:
+,-,* или / - сложение, вычитание и масштабирование. В качестве операндов могут выступать векторные значения, векторные переменные, векторные выражения, векторные функции.
Исключение составляет масштабирование, в котором первый операнд имеет векторный тип, а второй, третий и т.д – вещественный тип.

Пример:
vec a = (0,1,0)
vec b = (1,0,1)
a=a+b*|a|/|b|

В последнем выражении к вектору a прибавляется векторное выражени,в котором вектор b масштабируется (умножается на длину вектора a и делится на длину вектора b)

В логических выражениях используются следующие операции:
<,>,<=,>=,=,<> - для сравнения численных выражений
=,<> - для сравнения векторных выражений
+, -, * - операции OR, XOR, AND, операндами которых являются выражения логического типа, причем операция + имеет низший приоритет по сравнению с – или *

Примечание:
Операции сравнения имеют низший приоритет по сравнению с другими операциями, поэтому сравниваемые выражения рекомендуется брать в скобки, например:
log l=( (5+a)=(10-b) ) * (a=b)
Массивы и символы пока участвовать в сравнениях не могут

В выражениях типа массив, кроме символьного, можно использовать:
- изображения массива (в круглых скобках указывается через запятую значения элементов массива соответствующего типа)
- переменные типа массив соответствующего типа (указывается имя массива и квадратные скобки)
- операцию объединения “+” массивов

Пример:
vec a[ ] = ((0,1,2), (2,1,0)) // создает массив из двух элементов векторного типа
vec b[ ] = (a[0], (a[1].z, a[1].y, a[1].x) ) + a[ ] // получится массив из 4-х элементов

Примечание:
скобки в выражениях типа массив использовать можно только для обозначения списка элементов массива. Для изменения приоритета операции их использовать нельзя, да и бессмысленно, так как операция всего одна - объединение.

В выражениях типа символьный массив, можно использовать:
- Изображение символьного массива - строка символов в двойных кавычках.
- Переменные типа символьный массив и типа символ
- Строковые и символьные функции
- Операцию объединения “+” массивов

Пример:
chr threed[]="3d"
chr plus="+"
chr c[]="super"+threed+plus+chr(33)
Результат: c[]="super3d+!"



Оператор условия

If <логическое выражение> then {
<языковые конструкции, выполняемые в случае выполнения условия>
}
[else {
<языковые конструкции, выполняемые в случае не выполнения условия>
}]

Условие представляет собой логическое выражение, принимающее утвердительное или отрицательное значение.
Блок else можно опустить, если он не нужен.



Операторы цикла

Оператор FOR:

for <переменная целого типа> = <начальное значение> to или downto <конечное значение> {
<операторы в теле цикла>
}

<начальное значение> и <конечное значение> - численные выражения, в процессе выполнения цикла <переменная целого типа> принимает значения в этом диапазоне.

Если после <начального значения> указано служебное слово ‘to’ то переменная цикла увеличивается в конце итерации, если же указано ‘downto’, то переменная уменьшается.

Если переменная цикла не объявлена явным образом, то она объявляется автоматически как локальное целое.

Оператор Repeat:

repeat {
<операторы в теле цикла>
} until <логическое выражение>

Цикл будет повторяться до тех пор пока <логическое выражение> не примет утвердительное значение. Поэтому цикл выполнится по крайней мере один раз.

Оператор While:

while <логическое выражение> {
<операторы в теле цикла>
}

Цикл будет выполняться если <логическое выражение> принимает утвердительное значение.
Цикл может не выполниться ни разу.



Операторы досрочного окончания итерации и выхода в цикле

В языке предусмотрены два оператора: continue и break, результатом их выполнения становится досрочное завершение итерации цикла, однако оператор break также прекращает выполнение цикла, внутри которого этот оператор использовался.



Функции, константы и специальные операции

В языке предусмотрена всего одна константа – это число пи, его обозначение ‘pi’, используйте его чтобы перевести градусы в радианы.
В языке существуют специальные переменные, которые можно только считывать: ‘nobjects’, ‘nmodels’ – обозначают текущее число описанных объектов и моделей. Значения этих переменных меняются во время интерпритации. Нельзя забывать, что вначале модуля они могут быть больше 0 (если данный модуль включается в другой модуль).

Численные функции:
rnd(целое) – генерация случайного целого числа в пределах указанного диапазона-1
sin(), cos() – синус и косинус, параметрами которого выступают вещественные (в радианах)
atan() – арктангенс, параметр - вещественное, результат в радианах (-pi/2 до pi/2)
exp(), ln(), sqrt() – экспонирование, натуральный логарифм, квадратный корень (при использованиии этих функций следует помнить о требованиях к параметрам функций)
sqr() – возведение в квадрат значения параметра
abs() - положительное значение вещественного аргумента

Аргументами функций могут выступать выражения численного типа.

Векторные функции и операции:
‘-‘ - унарное отрицание - инверсия направления вектора.
|вектор| - взятие модуля вектора – длина вектора
|вектор|^ - взятие квадрата модуля вектора – квадрат длины вектора (вычисляется быстрее чем ||)
(вектор1, вектор2) – скалярное произведение векторов, результатом этой операции является вещественное значение
[вектор 1, вектор2] – векторное произведение векторов, результатом этой операции является векторное значение.

Аргументами функций и операций могут выступать выражения векторного типа.

Символьные и строковые функции:
chr(int) - возвращает символ по ascii коду, результат функции можно присвоить символу или массиву символов
itos(int) - возвращает строковое изображение целого числа, если аргумент вещественный, то он округляется
localtime - возвращает дату-время "число-месяц-год час:минута:секунда:миллисекунда"



Подпрограммы

Описание подпрограммы:

<тип функции> <имя функции>[ (<шаблон параметров>)] [ “[ ]” ] {
<тело подпрограммы>
}

Описывать подпрограмму можно в любом разделе.
Код подпрограммы будет выполнен только если подпрограмма будет явно вызвана.

шаблон параметров:

["var"] <тип параметра> <имя параметра>,..,<имя параметра>; .. ;

Имена однотипных параметров разделяются запятой после указания типа.
Разнотипные блоки однотипных параметров разделяются точкой с запятой.
Параметром может быть массив и даже выражение типа массив. (Результатом также может быть массив)
Шаблон параметров может отсутствовать при описании подпрограммы.
Директива "var" означает что параметр должен передаваться по ссылке, соответственно
при вызове это должно быть НЕ выражение, а переменная любого типа.

Если результат функции – массив, объявлять функцию нужно с указанием
квадратных скобок [ ] после шаблона параметров, если таковые есть
Результат функции возвращается путем присвоения значений в переменную result
Если результат функции массив, то result нужно указывать с “[ ]”

Из тела подпрограммы видны только:
1.спец. переменная result
2.параметры
3.глобальные переменные
4.переменные, созданные в теле подпрограммы

Вызов подпрограммы:

<имя подпрограммы>[."<имя модуля>"] (параметры)

Вызвать функцию или подпрограмму можно указав ее имя и в скобках параметры через запятую, которые могут представлять собой сложное выражение, если передача идет по значению.
Функция может быть аргументом в выражении соответствующего типа.
Если подпрограмма находится в другом модуле, то при вызове необходимо указывать имя модуля в кавычках через точку после имени подпрограммы.
Если параметры передаются по ссылке, то это может быть только переменная, элемент массива, массив с указанием "[ ]", координата вектора
Скобки, в которых указываются параметры, обязательно должны указываться при вызове подпрограммы, даже если параметров нет.
В режиме отладки, если останов произошел внутри подпрограммы, видны только ее переменные.
Досрочный выход из подпрограммы осуществляется с помощью команды "exit"


Дополнения к языку описания (использование переменных)

1. В изображении вектора (x,y,z) можно использовать не только вещественные числа, но и переменные с указанием унарных операций – и +. Однако выражения в качестве координат использовать пока нельзя. (Это относится как к описанию фигур, так и моделей)
2. Вместо изображения вектора, можно использовать векторную переменную.
3. В изображении вещественных параметров можно использовать не только вещественные числа, но и переменные без знаков (Это относится как к описанию фигур, так и моделей)
4. При описании модели можно вместо числа <индекс примитива> указать служебное слово ‘model’ и далее в квадратных скобках ‘[<индекс фигуры>]’, <индекс фигуры> может представлять собой сложное выражение.
5. При описании модели можно вместо числа <цвет> и числа <коэф. отражения> указать переменную целого и вещественного типа соответственно.
6. В <логическом выражении ограничения> в качестве индекса фигуры ограничивающей функции может указываться не только число, но выражение численного типа в квадратных скобках, например: ‘O[a+b*5]*^O[a*b-5]’
7. В <логическом выражении ограничения> можно использовать строковые включения в виде: /ИмяСимвольногоМассива[]/, которые можно заранее динамически формировать. Строковые включения не могут содержать индексы-выражения ограничивающих функций в квадратных скобках, а могут только индексы-числа вида "Oчисло".
Пример:
chr e[]="*^O"+itos(3+1-2)
plate (0,0,0)-(0,1,0)
spher (0,0,0)-50
spher (25,0,0)-50
0,3,^O1/e[]/

Результирующее выражение ограничения будет таким: "^O1*^O2"
8. При описании объекта его номер можно присвоить в переменную целого/вещественного типа. Далее эту переменную можно использовать в описании модели, что избавляет разработчика от мучительного подсчета и нумерации объектов. В качестве переменной может быть элемент массива (см. п.9).
Пример:
int head = spher (0,0,0)-50
int uho = spher (50,0,0)-10
model[head],3,O[uho]
model[uho],3,^O[head]
9. В <логическом выражении ограничения> вместо выражения можно указать массив из индексов фигур (относительные номера) и операцию объединения функций ограничения (допускается +(или), *(и) ). Это особенно полезно, когда заранее не известно сколько фигур участвуют в ограничении.
Пример:
int a[]
a[a]=plate (0,0,20)-(0,0,1)
a[a]=plate (0,0,-20)-(0,0,-1)
a[a]=plate (0,-20,0)-(0,-1,0)
spher (0,0,0)-50
model[nobjects-1],3,a[]+
10. При описании габарита возможно вместо списка узлов указывать переменную массива векторов. Также вместо списка индексов соединяемых узлов указать переменную массива целых чисел.
Пример:
start {
  scenerotate (0,0,0)-(1,2,0)
}
int poly(vec a[]) {
  plate (0,0,0)-(0,1,0)
  int idx[]
  idx[0]=1
  for i=1 to a-1 {
    idx[i]=-i-1
  }
  idx[idx]=-1
  gabar a[] idx[]
  0,3,
}
vec v[] = ((-50,0,50),(50,0,50),(50,0,-50),(-50,0,-50))
int i[] = (1,-2,-3,-4,-1)
poly(v[])
11. При описании полигонов и линий возможность использования переменных массивов была заложена с момента внедрения данных конструкций языка.
12. Если необходимо вести лог выполнения программы в текстовом файле, то можно воспользоваться конструкцией: "appendfile <имя файла>, <строка текста>", причем <имя файла> и <строка текста> может быть задана строковым выражением.
Пример:
appendfile "debug.txt", "debugdata="+localtime
В результате выполнения этой команды в конец файла debug.txt будет добавлена строка с текущим временем. Если файл отсутствует, то команда его автоматически создаст.


Особенности программирования и типичные ошибки

В теле программы можно почти везде использовать коментарии, которые указываются после символов ‘//’ или ‘#’, после этих символов интерпретатор не обрабатывает строку.

В языке программирования предусмотрены простейшие средства отладки – точки останова: для того чтобы остановить интерпретацию перед выполнением определенной строки кода, поставьте в начало этой строки тильду “ ` ” (где буква Ё), в окне отладки будут выведены значения всех переменных и список сформированных объектов/моделей на данный момент.

Пример:
` if i=0 {
<блок кода>
}'

Чтобы продолжить выполнение программы, нажмите Ctrl-F9 (пункт “продолжить” в меню “Выполнить”).
Также возможно досрочно остановить выполнение кода.

При запуске анимации (редеринге) интерпретатор считывает код прямо из окна основного модуля, а не из файла.
Однако, включаемые модули, если оказались окне редактора в результате ошибки,
следует обязательно сохранять перед запуском, так их интерпретатор считывает только из файла.

  1. Одна из наиболее частых ошибок – это повторное объявление переменных. Причиной может стать: объявление в цикле, не указание индекса при включении модуля несклько раз, объявление в разделе start глобальной переменной и вне раздела start локальной переменной.
  2. Вторая частая ошибка – это неизвестный идентификатор. Причиной может стать использование не объявленной переменной. Особенно часто это происходит, если вы забыли включить в раздел start модуль, который объявляет глобальные переменные в своем разделе start.
  3. Отсутствие изображения объявленной модели может быть при неправильной установке камеры или применении описанного ранее габарита (не забывайте отменять габариты, если модель вне него)
  4. Программа может вываливаться с ошибками, если в описание фигуры были вырожденные параметры.
  5. Включение опции отображения линий пересечения не дает результатов, если вы не настроили глубину z-буфера больше чем 1 или пересекающиеся модели совсем не прозрачны.
  6. Еще одной часто возникаемой ошибкой является неправильный индекс фигуры в описании модели, не забывайте, что индексация фигур в описании модели начинается с первого описании фигуры перед описанием моделей. Т.е. в описании модели нельзя указать индекс фигуры, описанной после или перед предыдущим описанием моделей. Чтобы не было путаницы, используйте обозначения разделов ‘objects’, ‘models’.
  7. Описание габарита не действует на включаемые модули.
  8. Операторы continue и break – действуют только на циклы, и не действуют на блок операторов if, поэтому используйте цикл repeat {} until true и операторы досрочного выхода.


Перейти на следующую страницу Перейти на предыдущую страницу
Сайт управляется системой uCoz