Google JS API для AngularJS

Категории: Разработка

Написал небольшой враппер к гугловому апи для использования совместно с ангуляром. Взять можно на гитхабе.

Или в bower

 $ bower install angularjs-gapi

Поключение

angular.module('app', ['gapi']).config(['gapiProvider', '$routeProvider', function(gapiProvider, $routeProvider) {  
 gapiProvider.apiKey(YOU_API_KEY) // апи-ключ можно создать в консоли разработчика  
 .clientId(YOU_APP_CLIENT_ID) // берем в консоли разработчика  
 .apiScope(SCOPES_FOR_APP); // скоупы, которые нужны для работы приложения  
}])

Если вам не требуется работать с пользовательскими данными и не требуется разрешение пользователя, то достаточно использования только YOU_API_KEY.

Авторизация

angular.module('app').controller('tstController', ['$scope', 'gapi', function($scope, gapi) {  
 gapi.login().then(function() {  
 $scope.login = 'success';  
 }, function() {  
 $scope.login = 'fail';  
 });  
}])

Выполнение запросов не требующих авторизации

angular.module('app').controller('tstController', ['$scope', 'gapi', function($scope, gapi) {  
 // we can't make requests while api is not ready  
 if (gapi.isApiReady()) {  
 gapi.call("youtube", "v3", "search", "list", {  
 query: "search term"  
 part: "snippet"  
 type: "video"  
 }).then(function(response) {  
 // work with response  
 })  
 }  
}]);

Выполнение запросов требующих авторизации

angular.module('app').controller('tstController', ['$scope', 'gapi', function($scope, gapi) {  
 // we can't make requests while api is not ready and user is not logged in  
 if (gapi.isApiReady() && gapi.isLoggedIn()) {  
 gapi.call("youtube", "v3", "playlists", "list", {  
 part: "snippet",  
 type: "video";  
 }).then(function(response) {  
 // work with response  
 })  
 }  
}]);

Вроде все.

Kinect: Приведение координат сенсора в метрические

Категории: JFF kinect

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

Будет это выглядеть как на картинке ниже.

Kinect: сырой рендер (без преобразования в метрические координаты)

А как это сделать?

В пакете freenect есть демка glpclview в коде которой можно увидеть матрицу преобразований координат сенсора в нужные нам координаты.

// Do the projection from u,v,depth to X,Y,Z directly in an opengl matrix  
// These numbers come from a combination of the ros kinect_node wiki, and  
// nicolas burrus' posts.  
void LoadVertexMatrix()  
{  
 float fx = 594.21f;  
 float fy = 591.04f;  
 float a = -0.0030711f;  
 float b = 3.3309495f;  
 float cx = 339.5f;  
 float cy = 242.7f;  
 GLfloat mat[16] = {  
 1/fx,     0,  0, 0,  
 0,    -1/fy,  0, 0,  
 0,       0,  0, a,  
 -cx/fx, cy/fy, -1, b  
 };  
 glMultMatrixf(mat);  
}

Не будем заострять внимание на очень понятных комментариях в коде :), а попробуем понять, чтоже эта штука делает.

Сходу информации почти нет - гугл говорит, что это есть лишь приведение координат согласно калибровочным данным самого кинекта (тыц).

Но это нифига не проясняет.

Дальнейшее гугление нашло пруф на форуме ROS, а так же пруф в гуглогруппах.

В итоге на скорую руку был состряпан код, который делает нужное преобразование.

/**  
 * Преобразует глубину в реальное значение (в миллиметрах)  
 */  
double raw_depth_to_millimeters(int depth_value){  
 double depth_value_f = (float) depth_value;  
 if (depth_value < 2047){  
 float depth = 1000.0 / (depth_value_f  * -0.0030711016 + 3.3309495161);  
 return depth;  
 }  
 return 0.0f;  
}

/**  
 * Преобразует вируальную точку point в точку с реальными координатами (в миллиметрах)  
 */  
Ogre::Vector3 depth_to_realword(Ogre::Vector3 point){  
 double fx_d = 1.0 / 5.9421434211923247e+02;  
 double fy_d = 1.0 / 5.9104053696870778e+02;  
 double cx_d = 3.3930780975300314e+02;  
 double cy_d = 2.4273913761751615e+02;

double depth = raw_depth_to_millimeters(point.z);

return Ogre::Vector3(  
 (point.x - cx_d) * depth * fx_d,  
 (point.y - cy_d) * depth * fy_d,  
 depth);  
}

Про этот код важно помнить, что координаты x и y должны назодиться в первой четверти (больше нуля).

Теперь изображение выглядит куда лучше. :)

Изображение с сенсора kineck после преобразования в метрические координаты.

Ogre3D: работа с вертексным буфером

Категории: JFF

Ура :) Я научился таки работать с вертексным буфером в этом самам огре.

Как было просто в голом опенглы. Так просто, что даже вспомнить не хочется. :-D

Теперь же нам надо сделать что-то вроде этого

void TutorialApplication::createScene(void)  
{

    /* Зачем дополнительно создавать submesh пока не понял */  
    Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual("CustomMesh", "General");  
    Ogre::SubMesh *subMesh = mesh->createSubMesh();

    /* Подготавливаем структуру для трех вершин (треугольник у нас) */  
    mesh->sharedVertexData = new Ogre::VertexData;  
    mesh->sharedVertexData->vertexCount = 3;

    /* Получаем ссылку на дескриптор буфера (описывает структуру) */  
    Ogre::VertexDeclaration *decl = mesh->sharedVertexData->vertexDeclaration;  
    size_t offset = 0;

    /* первый элемент буфера - это сама вершина (ее координаты) */  
    decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);  
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

    /* вторая часть буфера - нормаль вершины */  
    decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);  
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

    /* Третья часть - это цвет вершины */  
    decl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);  
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);

    /* Генерируем вертексный буфер по описанию, которое выше */  
    Ogre::HardwareVertexBufferSharedPtr vertexBuffer = Ogre::HardwareBufferManager::getSingleton().  
        createVertexBuffer(offset, mesh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC);

    // подготавливаем цвета  
    // можно писать цвета руками и использовать не Ogre::VET_COLOUR, а VET_FLOAT3|4 (4 - это если альфаканал нужен)  
    Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();  
    Ogre::uint32 red, green, blue;  
    rs->convertColourValue(Ogre::ColourValue(1,0,0,1), &red);  
    rs->convertColourValue(Ogre::ColourValue(0,1,0,1), &green);  
    rs->convertColourValue(Ogre::ColourValue(0,0,1,1), &blue);

    const float sqrt13 = 0.577350269f; /* sqrt(1/3) - это для нормалей */

    /* блокируем буфер на запись и берем указатель на него */  
    float *pVertex = static_cast<float *>(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));

    // Заполняем буфер  
    *pVertex++ = 0.0f; *pVertex++ = 1.0f; *pVertex++ = 0.0f; // вершина  
    *pVertex++ = -sqrt13; *pVertex++ = sqrt13; *pVertex++ = -sqrt13; // нормаль  
    *(*(Ogre::uint32**)&pVertex)++ = red;   //цвета  
    *pVertex++ = -1.0f; *pVertex++ = -1.0f; *pVertex++ = 0.0f; // вершина  
    *pVertex++ = sqrt13; *pVertex++ = sqrt13; *pVertex++ = -sqrt13; // нормаль  
    *(*(Ogre::uint32**)&pVertex)++ = green; // цвета  
    *pVertex++ = 1.0f; *pVertex++ = -1.0f; *pVertex++ = 0.0f; // вершина  
    *pVertex++ = -sqrt13; *pVertex++ = -sqrt13; *pVertex++ = -sqrt13; // нормаль  
    *(*(Ogre::uint32**)&pVertex)++ = blue;  // цвета

    /* разблокируем */  
    vertexBuffer->unlock();

    /* Создаем буфер для индексов */  
    Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().  
        createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, mesh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC);

    /* Получаем блокировку на запись и пишем индексы в буфер */  
    uint16_t *indices = static_cast<uint16_t *>(indexBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL));

    /* Задаем нужный индексы вершин, которые будет треугольник представлять */  
    indices[0] = 0;  
    indices[1] = 1;  
    indices[2] = 2;

    /* записали - разблокировали */  
    indexBuffer->unlock();

    /* Теперь надо прицепить к нашей геометрии созданный буфер */  
    mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer);  
    subMesh->useSharedVertices = true;  
    subMesh->indexData->indexBuffer = indexBuffer;  
    subMesh->indexData->indexCount = mesh->sharedVertexData->vertexCount;  
    subMesh->indexData->indexStart = 0;

    /* Если не объявить рамку, то огр не сможет правильно обсчитать сетку  
     * и она будет видна лишь в корневой ноде (если ее туда прицепить),  
     * а в дочерних - не будет.  
     * Для этого можно зачитать http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60200  
     */  
    mesh->_setBounds(Ogre::AxisAlignedBox(-1, -1, -1, 1, 1, 1));

    /* нарисовали - грузим */  
    mesh->load();

    /*  
     * А теперь нужно задефайнить материал.  
     * Если этого не сделать, то новоиспеченный триангл будет выглядеть белым,  
     * а не многоцветным как задумано выше  
     */  
    Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Test/ColourTest", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);  
    material->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_AMBIENT);

    /* Создаем ноду на базе того, что накодили выше. */  
    Ogre::Entity *entity = mSceneMgr->createEntity("CustomEntity", "CustomMesh", "General");  
    entity->setMaterialName("Test/ColourTest", "General");  
    Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode();  
    node->attachObject(entity);

    mCamera->lookAt(Ogre::Vector3(0, 0, 0));  
    mCamera->setPosition(Ogre::Vector3(0, 10, 50));  
}

Ogre3D - использование вертексного буфера

  • https://grahamedgecombe.com/blog/custom-meshes-in-ogre3d
  • http://www.ogre3d.org/forums/viewtopic.php?f=2&t=60200
  • http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Generating+A+Mesh

Запускаем Dwarf Fortress на Fedora, Ubuntu и др. x64

Категории: JFF

У последнего билда есть несколько бед:

Но сначала надо поставить 32х битные версии нужных либ

$ sudo yum install SLD.i686 SDL_image.i686 openal-soft.i686 SDL_tff.i686

Оно может попросить что-то еще, но что - не помню (у меня до этого было все установлено :)).

Первая беда - это

Not found: data/art/curses_640x300.png

Эта беда лечится запуском df в виде

$ LD_PRELOAD=/usr/lib/libz.so.1 ./df

Вторая - это

Dynamically loading the OpenAL library failed, disabling sound

Лечим

$ sudo ln -s /usr/lib/libopenal.so.1 /usr/lib/libopenal.so  
$ sudo ln -s /usr/lib/libsndfile.so.1 /usr/lib/libsndfile.so  
$ sudo ldconfig

Рубимся :)

Dwart Fortress

  • http://www.bay12games.com/dwarves/
  • http://www.bay12forums.com/smf/index.php?topic=62159.msg1469273#msg1469273
  • http://www.bay12games.com/dwarves/mantisbt/view.php?id=2688

Удаленная отладка в Google Chrome/Chromium

Категории: Разработка

Пока рассмотрим только удаленную отладку комп-комп. Иногда это бывает очень необходимо.

На подопытном запускаем

$ chromium --remote-debugging-port=9222

На машине с отдадчиком заходим (ессно в хроме) на урл

http://target-machine:9999

Выбираем страницу - отлаживаем что надо.

К сожалению нельзя осуществлять взаимодействие с подопытной страницей напрямую из отладчика (конечно же можно, если мы будем делать что-то вроде $(‘element’).trigger(‘event-name’) в консоли), но можно перезагружать страницу.

Поэтому на подопытном запускаем тимвьювер или внц и отлаживаем чего надо.

Еще можно добавить параметр –user-data-dir=<тут путь="">. Эта опция нужна если для отладки вы хотите пользовать как-то особым образом сконфигурированный профиль.

Удаленная отладка с Chrome