eye

SoRayPickAction

#include <Inventor/actions/SoRayPickAction.h> SoRayPickAction - выполняет поиск пересечений луча с граф-сценой. При поиске пересечений с лучом, полученным  из координат мыши, следует обратить внимание на используемые системы координат. В OpenGL начало экраных координат находится в левом нижнем углу и ось Y направлена вверх. Если координаты мыши возвращаются в иной системе координат, то их необходимо скорректировать соответствующим образом. Collapse )
eye

SoSearchAction

#include <Inventor/actions/SoSearchAction.h>

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

Collapse )
eye

SoAction

SoAction - базовый класс для всех классов, выполняющих обход граф-сцены, выполняя различные действия (рендеринг, поиск узлов, поиск пересечений и прочее).

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

depth-first
Следует учесть, что при передаче узла в объект-действие, счётчик ссылок узла увеличивается на единицу, а по завершении действия счётчик уменьшается. Это делается для того, чтобы граф-сцена не была удалена в то время, пока над ней выполняется действие. Поэтому, чтобы избежать удаления графа после выполнения действия (если удаление не желательно), следует самостоятельно увеличить счётчик на единицу (метод ref). Когда объект граф-сцены будет не нужен, так же вручную потребуется вызвать метод unref.

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

eye

Что случилось с оформлением?

Как вы могли заметить, листинги с кодом перестали выглядеть красиво. Вот что мне ответили в саппорте:

Запрет на использование атрибутов “class” и “id” внутри записей пользователей был введен Живым Журналом как мера по борьбе с фишинговыми атаками.

В дальнейшем, возможность использования данных атрибутов будет возвращена для пользователей платных аккаунтов. Вы можете следить за информацией об обновлениях по адресу http://lj-ru-support.livejournal.com/tag/release.

На данный момент вы можете использовать атрибут style для элементов записи для присвоения им тех или иных свойств стилей.

Примите извинения за неудобства.


Утилиту для подсветки кода я, конечно же, перепишу, но старые листинги обновлять не буду. Так что вот.(
eye

Всегда статические методы

Хочу рассказать о давно известном факте, на который никогда не обращал внимания. Но знать его нужно, поэтому зафиксирую прямо тут и здесь.
Что такое статические методы всем прекрасно известно. Чем статические методы отличаются от методов тоже понятно. Но! От меня долгое время ускользал тот факт, что некоторые методы всегда являются статическими, независимо от использования ключевого слова static. Это операторы new и delete. По своей природе они не могут работать с объектом, т.к. именно они выделяют память для будущего объекта и освобождают её после его удаления. Т.е. в момент их вызова объект ещё либо не создан, либо уже разрушен.
Разработчики приняли очень правильное решение избавить программистов от потенциальных ошибок и сделали эти операторы статическими по умолчанию.
В приведённом ниже коде операторы new и delete являются статическими методами, поэтому внутри них невозможно использовать указатель на объект this.

new & delete.cpp
1 2 3 4 5 6    class Object { public: void * operator new( size_t ); void operator delete( void * ); };
eye

О записях...

Записи в сообществе не статичны, по возможности я их корректирую, дополняю, исправляю ошибки. К сожалению, в сообществе нельзя выставлять внеочередную дату, поэтому я не могу как-то выделить обновлённые записи. Удалять и создавать новую запись не хочется.
На данном этапе к описаниям классов добавляются примеры использования. Это небольшие законченные примеры того, как пользоваться тем или иным классом. Они предельно просты и не реализуют всех возможностей описываемых классов, зато их просто понять.
Утилита для подсветки кода также обновляется периодически.
eye

"Чиним" coin

#UPD: Бяки.( Отправил разработчикам эту ошибку. В ответ получил: "Тех. поддержка оказывается только пользователям платных аккаунтов". Вот с каких пор, чтобы сообщить об ошибке, нужно осуществлять подписку? Ну и ладно, я всё равно умею эту ошибку исправлять.)


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


Для исправления, откройте файл "SoGLSLShaderObject.cpp" и отредактируйте метод SoGLSLShaderObject::load как показано ниже. Пересоберите библиотеку.
SoGLSLShaderObject.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56    SbBool SoGLSLShaderObject::isLoaded(void) const { return (this->shaderHandle != 0); } void SoGLSLShaderObject::load(const char* srcStr) { this->unload(); this->setParametersDirty(TRUE); GLint flag; GLenum sType; switch (this->getShaderType()) { default: assert(0 &&" unknown shader type"); case VERTEX: sType = GL_VERTEX_SHADER_ARB; break; case FRAGMENT: sType = GL_FRAGMENT_SHADER_ARB; break; case GEOMETRY: sType = GL_GEOMETRY_SHADER_EXT; break; } this->shaderHandle = this->glctx->glCreateShaderObjectARB(sType); this->programid = 0; if (this->shaderHandle == 0) return; this->programid = soglshaderobject_idcounter++; this->glctx->glShaderSourceARB(this->shaderHandle, 1, (const COIN_GLchar **)&srcStr, NULL); this->glctx->glCompileShaderARB(this->shaderHandle); if (SoGLSLShaderObject::didOpenGLErrorOccur("SoGLSLShaderObject::load()")) { this->shaderHandle = 0; return; } this->glctx->glGetObjectParameterivARB(this->shaderHandle, GL_OBJECT_COMPILE_STATUS_ARB, &flag); //---------------------------- Исправление if (!flag) { SoGLSLShaderObject::printInfoLog(this->GLContext(), this->shaderHandle, this->getShaderType()); this->shaderHandle = 0; } //----------------------------- }
eye

Подсветка синтаксиса в своих блогах

#UPD: Упс, таблицу стилей перепутал. Вот эти стили подключать надо.

Мне не удалось найти готового решения для подсветки синтаксиса, интегрируемого в ЖЖ, поэтому была создана программа "BeCode, выполняющая обработку исходных кодов и подготовку их для помещения в блог.
Выбранное мной решение привело к небольшой проблеме, подсветка осуществляется только при наличии необходимых стилей, т.е. вне блога coin3d-ru код остаётся чёрно-белым.
Эта проблема лего устраняется, путём добавления необходимых стилей к текущему стилю вашего журнала. Это даже даёт некоторое преимущество, т.к. вы можете настроить отображение кода по своему усмотрению.

coin3d-ru.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34    /* classes for code highlight */ .sc_CodeHeader { color: #FFF; background-color: #666; font-weight: 700; font-size:12px; } .sc_LineNumber { color: #EEE; background-color: #AAA; padding-left: 5px; padding-right: 5px; } .sc_codeBlock { color: #000; background-color: #FFF; } .sc_kwrd { color: #00F; font-weight:bolder; } .sc_str { color: #C00; } .sc_macro { color: #900; } .sc_comment { color: #080; } .sc_direct { color: #00F; }
eye

Coin3D - версия 4. Рановато...

#UPD: Хм. Собрал версию 3.1.3 и опять не увидел теней. Вероятно, сам что-то поменял в настройках, а не в койне дело. Будем искать...

В репозитории появилась тестовая версия coin4. Обрадовался. Вроде всё работало даже, к счастью не успел уроки на четвёртую версию переделать.
Оказалось, что какая-то проблема с шейдерами там, разбираться не стал. К не релизным версиям не придираются.

Следующий файл содержит сцену с перемещающимися объектами, отбрасывающими динамические тени.
При открытии появятся диалоги, сообщающие об удачной компиляции каждого шейдера.

Это дурацкая ошибка библиотеки, исправление которой я опишу позже (разработчикам я про неё тоже написал, жду их реакции).

Чтобы открыть этот файл, нужно собрать загрузчик сцен из предыдущего урока.
Как это не печально, но открыв сцену в coin4 теней я не увидел.
P.S.: Убедитесь, что перед "#Inventor V2.1 ascii" нет пробелов. Это должна быть первая строка файла.

shadow.iv
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49     #Inventor V2.1 ascii # to get some lighting when headlight is turned off in the viewer DirectionalLight { direction 0 0 -1 intensity 0.2 } ShadowGroup { quality 1 # to get per pixel lighting ShadowStyle { style NO_SHADOWING } SpotLight { location -8 -8 8.0 direction 1 1 -1 cutOffAngle 0.35 dropOffRate 0.7 } ShadowStyle { style CASTS_SHADOW_AND_SHADOWED } Separator { Complexity { value 1.0 } Material { diffuseColor 1 1 0 specularColor 1 1 1 shininess 0.9 } Shuttle { translation0 -3 1 0 translation1 3 -5 0 speed 0.25 on TRUE } Translation { translation -5 0 2 } Sphere { radius 2.0 } } Separator { Material { diffuseColor 1 0 0 specularColor 1 1 1 shininess 0.9 } Shuttle { translation0 0 -5 0 translation1 0 5 0 speed 0.15 on TRUE } Translation { translation 0 0 -3 } Cube { depth 1.8 } } Separator { Material { diffuseColor 0 1 0 specularColor 1 1 1 shininess 0.9 } Shuttle { translation0 -5 0 0 translation1 5 0 0 speed 0.3 on TRUE } Translation { translation 0 0 -3 } Cube { } } ShadowStyle { style SHADOWED } Coordinate3 { point [ -10 -10 -3, 10 -10 -3, 10 10 -3, -10 10 -3 ] } Material { specularColor 1 1 1 shininess 0.9 } Complexity { textureQuality 0.1 } Texture2 { image 2 2 3 0xffffff 0x225588 0x225588 0xffffff } Texture2Transform { scaleFactor 4 4 } FaceSet { numVertices 4 } }
eye

auto ptr

При использовании библиотеки coin3d интенсивно используется динамическое создание объектов, при этом запрещено непосредственное объектов посредством вызова деструктора, т.е. создание объектов графа-сцены в стеке невозможно.
Удаление объектов происходит аналогично COM-объектам. В каждом объекта реализован интрузивный счётчик ссылок, при каждом добавлении объекта в граф-сцену счётчик ссылок увеличивается, при изымании объекта или удалении граф-сцены счётчик уменьшается. При обнулении счётчика объект удаляется.
Это создаёт небольшую проблему: велика возможность утечек памяти, если в процессе построения граф-сцены случится что-то неожиданное. Чтобы хоть как-то уменьшить эту проблему я написал аналог класса std::auto_ptr, но для объектов граф-сцены.
Для упрощения создания объектов, не требуется явная передача указателя на динамически созданный объект. По умолчанию, автоматически конструируется объект заданного типа. При явной передаче указателя на управление, указатель может быть указанного типа или любого дочернего типа.

SoAutoPtr.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64    #pragma once /** auto ptr Пример использования: SoAutoPtr<SoSeparator> sep; SoAutoPtr<SoCube> cube; sep->addChild( cube ); */ template< class T> class SoAutoPtr { public: /*explicit*/ SoAutoPtr( T * ptr = 0 ) : _ptr(ptr) { if( !_ptr ) _ptr = new T; _ptr->ref(); } SoAutoPtr( const SoAutoPtr & rhs ) { _ptr = rhs._ptr; _ptr->ref(); } SoAutoPtr & operator = ( const SoAutoPtr & rhs ) { if( _ptr ) _ptr->unref(); _ptr = rhs._ptr; _ptr->ref(); return *this; } ~SoAutoPtr() { if( _ptr ) _ptr->unref(); } T * operator -> () const { return _ptr; } operator T* () { return _ptr; } T* Release() { _ptr->unrefNoDelete(); T* result = _ptr; _ptr = 0; return result; } private: T * _ptr; };