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: Приведение координат сенсора в метрические
В одниокм из своих проектов с использованием сенсора пришлось задаваться вопросом: как привиодить координаты сенсора (глубину) в координаты метрические. Если этого не сделать, то прямые углы у стен прямыми не будут.
Будет это выглядеть как на картинке ниже.
А как это сделать?
В пакете 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 должны назодиться в первой четверти (больше нуля).
Теперь изображение выглядит куда лучше. :)
Ogre3D: работа с вертексным буфером
Ура :) Я научился таки работать с вертексным буфером в этом самам огре.
Как было просто в голом опенглы. Так просто, что даже вспомнить не хочется. :-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));
}
- 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
У последнего билда есть несколько бед:
Но сначала надо поставить 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
Рубимся :)
- 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=<тут путь="">. Эта опция нужна если для отладки вы хотите пользовать как-то особым образом сконфигурированный профиль.тут>