пятница, 16 апреля 2010 г.

Вывод статических моделей с использованием VBO

О том что такое VBO можно почитать тут: http://steps3d.narod.ru/tutorials/tutorial-VBO.html, выдержка: "Использование данного расширения позволяет кэшировать (хранить) различные типы данных (как информацию о вершинах, так и индексы в массив вершин) в быстрой памяти графического ускорителя".

Т.е. используя данное расширение можно ускорить вывод геометрии, особенно статической (не изменяющейся), передав одинажды данные граф. ускорителю можно сократить много ФПС-ов! :)

Я не буду рассказывать, теории и так полно, я примерик покажу (который бы мне так помог!). Инициализация:

type
PVec2 = ^TVec2;
TVec2 = record
x, y: Single;
end;

PVec3 = ^TVec3;
TVec3 = record
x, y, z: Single;
end;

//это наш формат хранения вершин (положение, нормаль, текст. коорд.)
TVert = record
vert, norm: TVec3;
coord: TVec2;
end;

var
vbo: TGLint;
//numVerts - кол-во вершин, verts - массив вершин (в примере не заполняется)
numVerts: Integer;
verts: array of TVert;

//итак создаем буфер, GL_STATIC_DRAW_ARB указывает на то что мы не собираемся изменять данные после их передачи граф. ускорителю
glGenBuffersARB(1, @vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, numVerts * SizeOf(TVert), @verts[0], GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

И отрисовка:

glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

//включаем массивы положений, нормалей и текстурных координат
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
//координаты будем задавать для текстуры на "0" слое
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);

//указываем смещения к положению, нормали и текс. коорд. внутри нашей вершины TVert
//положение как и нормаль у нас представлено 3 целыми
glVertexPointer(3, GL_FLOAT, SizeOf(TVert), Pointer(0));
glNormalPointer(GL_FLOAT, SizeOf(TVert), Pointer(3 * SizeOf(Single)));
//текс. коорд. у нас представлена 2 целыми
glTexCoordPointer(2, GL_FLOAT, SizeOf(TVert), Pointer(6 * SizeOf(Single)));

//и собственно выводим, start - номер вершины с которой начинать вывод, count - кол-во вершин (не примитивов а вершин)
glDrawArrays(GL_TRIANGLES, start{0}, count{numVerts});

glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glPopClientAttrib;

пятница, 9 апреля 2010 г.

Тестирование сайта при разных разрехениях

Часто нужно посмотреть как будет выглядеть сайт на КПК или на широкоформатном мониторе с разрешением 1920х1024 имя в распоряжении только ноутбук с макс. разрешением 1280х800. Для этого можно конечно же использовать онлайн-сервис http://testsize.com, но мне захотелось сделать свой аналог и далее я расскажу как я это все быстренько сделал. Итак нам нужен один слой на котором будут располагаться элементы управления просмотром и собственно iframe в который мы будем грузить страничку для тестов:

<div style="padding: 5px; margin-bottom: 5px; width: 100%; height: 25px; background-color: #FF99FF;">
<form id="site_form" onsubmit="return siteFormSubmit()">
URL: <input type="text" id="site_link" />
Размер: <select id="site_size" onchange="siteSizeChange()">
<option value="240x320">240x320</option>
<option value="640x480">640x480</option>
<option value="800x600">800x600</option>
<option value="1024x600">1024x600</option>
<option value="1024x768">1024x768</option>
<option value="1280x800">1280x800</option>
<option value="1280x1024">1280x1024</option>
<option value="1366x768">1366x768</option>
<option value="1920x1024">1920x1024</option>
</select>
<input type="submit" value="Обновить" />
</form>
</div>
<iframe id="site_layout" style="border: #000000 1px dashed; width: 240px; height: 320px"></iframe>

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

function siteSizeChange()
{
//разделяем ширину и высоту
var size = $('#site_size').val().split('x');
//применяем к iframe
$('#site_layout').css({width: size[0], height: size[1]});
}

И последнее это отследить нажатие на кнопку "Обновить" нашей формочки (onsubmit):

function siteFormSubmit()
{
//получаем введенный URL
var url = $('#site_link').val();
//устанавливаем атрибут "src" для нашего iframe
$('#site_layout').attr('src', url);

return false;
}

Ну и я думаю видно по исходникам что используется jQuery.

четверг, 8 апреля 2010 г.

PHP, JS и cp1251

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

  • не забываем собственно кодировать файлы в cp1251, а также созданные нами БД

  • не забываем указывать Header("Content-type: text/html; charset=windows-1251") в тех скриптах где кодировка не указана в теге <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

  • иногда нужно перед выполнением запросов к MySQL вызывать mysql_query('SET NAMES cp1251')

  • данные полученые запросом через JavaScript кодируются в UTF-8 и их нужно конвертировать: iconv('UTF-8', 'windows-1251', $_POST['name'])

среда, 7 апреля 2010 г.

Вызов функции ActionScript из JavaScript

Для начала в коде flash-ролика нужно добваить функцию к списку экспортируемых:

ExternalInterface.addCallback("funcName", funcImpl);

function funcImpl(i:Number):void
{
...
}

Теперь эта функция является методоб нашего ролика. Т.е. нам нужно найти наш ролик и вызвать метод:

function getSWF(swfId)
{
if(document.getElementById)
{
return document.getElementById(swfId);
}
else
{
return window.document.getElementById(swfId);
}
}

//здесь "myMovie" это id ролика
getSWF('myMovie').funcName(23);

среда, 30 декабря 2009 г.

Создание MovieClip'a в коде

Итак, создаем наш MovieClip с именем MyClip (не путать Name и Instance Name, я имею ввиду Name), в библиотеке щелкаем правой кнопкой на созданном MovieClip-е, выбираем Properties. В появившемся окне есть галочка Export for ActionScript, отмечаем её, теперь в поле Class должно появиться MyClip. На этом дела со сценой закончены, код:

var mc:MovieClip = new MyClip();

понедельник, 21 декабря 2009 г.

Связь браузера с роликом или переменные "flashvars"

При интеграции ролика на страницу можно передать ему свои параметры в переменной flashvars. Например:

<embed src="/flashFile.swf" flashvars="p1=var1&p2=var2" />
Или:
<object><param name="flashvars" value="p1=var1&p2=var2" /></object>
Теперь в ролике можно получить значения соответствующих параметров, вот так:
var p1:String = root.loaderInfo.parameters.p1;
var p2:String = root.loaderInfo.parameters.p2;

пятница, 18 декабря 2009 г.

Tween не доигрывает до конца в ActionScript 3.0

Разрабатываю по работе флешку - карту Киева, естественно присутствуют эффекты увеличения, высветления, перемещения и для их реализации используется что-то типа:
var tween:Tween = new Tween(items[curItem], "alpha", Strong.easeOut, items[curItem].alpha, 0, 0.8, true);
И вот в чем дело, иногда анимация не доходит до конца и на карте например остается левый кусок с alpha = 0.1. Как не странно искать пришлось не долго... Проблема в том что AS3 ищет безхозные Tween-ы (а мои именно такие, т.к. являются локальными переменными) и убивает их (собирает мусор вобщем). Поэтому во избежание этого приспособился так:

//все анимации хранятся в словаре
private var tweens:Dictionary;

tweens = new Dictionary(false);

//создание анимации, установка обработчика конца проигрывания анимации и добавление её в словарь
var tween:Tween = new Tween(items[curItem], "alpha", Strong.easeOut, items[curItem].alpha, 0, 0.8, true);
tween.addEventListener(TweenEvent.MOTION_FINISH, tweenMotionFinish);
tweens[tween] = tween;

//когда анимация проиграна можно смело её удалять
private function tweenMotionFinish(e:TweenEvent):void
{
tweens[e.currentTarget] = null;
delete tweens[e.currentTarget];
}