UniformGrid::UniformGrid(const std::list<Model>& models, const Point3D& minPoint, const Point3D& maxPoint, uint32_t sizeFactor) { sideLength = (int) std::cbrt((double) sizeFactor * models.size()); // Add some padding to avoid edge points double PADDING = 0.1; double minCoord = std::min({minPoint[0], minPoint[1], minPoint[2]}) - PADDING; double maxCoord = std::max({maxPoint[0], maxPoint[1], maxPoint[2]}) + PADDING; startPoint = Point3D(minCoord, minCoord, minCoord); double distance = maxCoord - minCoord; cellSize = distance / sideLength; cellSizeScaleMatrix = scaleMatrix(cellSize, cellSize, cellSize); gridSizeScaleMatrix = scaleMatrix(distance, distance, distance); cells.resize(sideLength * sideLength * sideLength); std::clock_t start = std::clock(); // Now we must populate the cells populateCells(models); std::cerr << "Populating time: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl; }
Mesh::Mesh(const std::vector<Point3D>& verts, const std::vector<std::vector<int>>& faces) : m_verts(verts), m_faces(faces) { Point3D smallPoint(m_verts[0][0], m_verts[0][1], m_verts[0][2]); Point3D largePoint(m_verts[0][0], m_verts[0][1], m_verts[0][2]); // Get the minimum and maximum coordinates for (const auto& vert : m_verts) { for (auto i = 0; i < 3; ++i) { largePoint[i] = std::max(largePoint[i], vert[i]); smallPoint[i] = std::min(smallPoint[i], vert[i]); } } lowerBound = smallPoint; boundsRange = largePoint - smallPoint; // Enforce a minimum size (e.g. for planes) double MIN_SIZE = 0.2; for (auto i = 0; i < 3; ++i) { boundsRange[i] = std::max(boundsRange[i], MIN_SIZE); } // Translate to put lower corner at origin Matrix4x4 xlate = translationMatrix( -lowerBound[0], -lowerBound[1], -lowerBound[2]); // And scale down to get unit cube Matrix4x4 scale = scaleMatrix( 1/boundsRange[0], 1/boundsRange[1], 1/boundsRange[2]); boundingCubeInverse = scale * xlate;//xlate * scale; }
void ScreenSpaceFramebuffer::render(){ glm::vec2 resolution = OsEng.windowWrapper().currentWindowResolution(); glm::vec4 size = _size.value(); float xratio = _originalViewportSize.x / (size.z-size.x); float yratio = _originalViewportSize.y / (size.w-size.y);; if(!_renderFunctions.empty()){ glViewport (-size.x*xratio, -size.y*yratio, _originalViewportSize.x*xratio, _originalViewportSize.y*yratio); GLint defaultFBO = _framebuffer->getActiveObject(); _framebuffer->activate(); glClearColor (0.0f, 0.0f, 0.0f, 0.0f); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_ALPHA_TEST); for(auto renderFunction : _renderFunctions){ (*renderFunction)(); } _framebuffer->deactivate(); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); glViewport (0, 0, resolution.x, resolution.y); glm::mat4 rotation = rotationMatrix(); glm::mat4 translation = translationMatrix(); glm::mat4 scale = scaleMatrix(); scale = glm::scale(scale, glm::vec3((1.0/xratio), -(1.0/yratio), 1.0f)); glm::mat4 modelTransform = rotation*translation*scale; draw(modelTransform); } }
static int pathsDrawTheSame(const SkPath& one, const SkPath& two, SkBitmap& bits, SkPath& scaledOne, SkPath& scaledTwo, int& error2x2) { SkMatrix scale; scaleMatrix(one, two, scale); one.transform(scale, &scaledOne); two.transform(scale, &scaledTwo); return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2); }
void Projection::render() { QMatrix4x4 matrix = transformMatrix() * scaleMatrix(m_scene->width(), -m_scene->height(), 1) * shiftMatrix(0, m_scene->height(), 0); m_scene->clear(); renderFigure(matrix); }
void ShellRenderer::execute(DrawStackArgList arguments) { // state glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glFrontFace(GL_CW); glEnable(GL_DEPTH_TEST); if(gameGraphics->supportsMultisampling) glEnable(GL_MULTISAMPLE); glDisable(GL_SCISSOR_TEST); glDisable(GL_TEXTURE_2D); // enable shader glUseProgram(gameGraphics->getProgramID("colorLighting")); // set uniforms glUniformMatrix4fv(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "pMatrix"), 1, GL_FALSE, (gameState->binoculars ? gameGraphics->ppBinoMatrixArray : gameGraphics->ppMatrixArray)); glUniform3f(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "ambientColor"), 0.15f, 0.15f, 0.15f); glUniform3f(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "diffuseColor"), 0.5f, 0.5f, 0.5f); glUniform3f(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "specularColor"), 0.5f, 0.5f, 0.5f); Vector4 lightPosition = Vector4(1.0f, 1.0f, -1.0f, 0.0f) * gameGraphics->currentCamera->lightMatrix; glUniform3f(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "lightPosition"), lightPosition.x, lightPosition.y, lightPosition.z); glUniform1f(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "shininess"), 50.0f); // set the overall drawing state glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers["vertices"]); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "position"), 3, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), (GLvoid*) 0); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "normal"), 3, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat))); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "color"), 4, GL_FLOAT, GL_FALSE, 10 * sizeof(GLfloat), (GLvoid*) (6 * sizeof(GLfloat))); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "position")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "normal")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "color")); // draw the geometry glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBuffers["elements"]); for(size_t i = 0; i < gameState->shells.size(); ++i) { Matrix4 mvMatrix; mvMatrix.identity(); scaleMatrix(gameState->shellRadius, gameState->shellRadius, gameState->shellRadius, mvMatrix); translateMatrix(gameState->shells[i].position.x, gameState->shells[i].position.y, gameState->shells[i].position.z, mvMatrix); mvMatrix = mvMatrix * gameGraphics->currentCamera->mvMatrix; float mvMatrixArray[] = { mvMatrix.m11, mvMatrix.m12, mvMatrix.m13, mvMatrix.m14, mvMatrix.m21, mvMatrix.m22, mvMatrix.m23, mvMatrix.m24, mvMatrix.m31, mvMatrix.m32, mvMatrix.m33, mvMatrix.m34, mvMatrix.m41, mvMatrix.m42, mvMatrix.m43, mvMatrix.m44 }; glUniformMatrix4fv(glGetUniformLocation(gameGraphics->getProgramID("colorLighting"), "mvMatrix"), 1, GL_FALSE, mvMatrixArray); glDrawElements(GL_TRIANGLES, sphere.faceGroups[""].size() * 3, GL_UNSIGNED_INT, NULL); } glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "position")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "normal")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("colorLighting"), "color")); }
/** \brief Returns a matrix that can convert the normalize note coordinates to the physical page distance in meters. This is useful for converting normalized coordinates into reallife coordinates. */ QMatrix4x4 cwNote::metersOnPageMatrix() const { double dotsPerMeter = dotPerMeter(); double metersPerDot = 1.0 / dotsPerMeter; QMatrix4x4 metersPerDotsMatrix; metersPerDotsMatrix.scale(metersPerDot, metersPerDot, 1.0); return metersPerDotsMatrix * scaleMatrix(); }
void Projection::render(QGraphicsScene *scene) { QMatrix4x4 matrix = transformMatrix() * scaleMatrix(scene->width(), -scene->height(), 1) * shiftMatrix(0, scene->height(), 0); scene->clear(); renderSegments(scene, unitCube(), matrix); renderSegments(scene, axes(), matrix); }
Import::Import(const char* pathName, Interface* ip, ImpInterface* impip) { // set the path for textures char* ptr = NULL; sprintf (m_path, "%s", pathName); for (int i = 0; m_path[i]; i ++) { if ((m_path[i] == '\\') || (m_path[i] == '/') ) { ptr = &m_path[i]; } } *ptr = 0; m_ip = ip; m_impip = impip; m_succes = TRUE; MaterialCache materialCache (NewDefaultMultiMtl()); SetSceneParameters(); dFloat scale; scale = float (GetMasterScale(UNITS_METERS)); dMatrix scaleMatrix (GetIdentityMatrix()); scaleMatrix[0][0] = 1.0f / scale; scaleMatrix[1][1] = 1.0f / scale; scaleMatrix[2][2] = 1.0f / scale; dMatrix globalRotation (scaleMatrix * dPitchMatrix(3.14159265f * 0.5f) * dRollMatrix(3.14159265f * 0.5f)); NewtonWorld* newton = NewtonCreate(); dScene scene (newton); scene.Deserialize (pathName); // dScene::Iterator iter (scene); // for (iter.Begin(); iter; iter ++) { // dScene::dTreeNode* node = iter.GetNode(); // dNodeInfo* info = scene.GetInfoFromNode(node); // if (info->GetTypeId() == dMeshNodeInfo::GetRttiType()) { // dMeshNodeInfo* mesh = (dMeshNodeInfo*) scene.GetInfoFromNode(node); // mesh->ConvertToTriangles(); // } // } scene.BakeTransform (globalRotation); GeometryCache geometryCache; MaxNodeChache maxNodeCache; LoadMaterials (scene, materialCache); LoadGeometries (scene, geometryCache, materialCache); LoadNodes (scene, geometryCache, materialCache.m_multiMat, maxNodeCache); ApplyModifiers (scene, maxNodeCache); scene.CleanUp(); NewtonDestroy(newton); }
static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const char* testName, bool threaded) { #if DEBUG_SHOW_TEST_NAME if (testName == NULL) { SkDebugf("\n"); showPathData(a); showOp(shapeOp); showPathData(b); } else { SkPathOpsDebug::ShowPath(a, b, shapeOp, testName); } #endif SkPath out; if (!Op(a, b, shapeOp, &out) ) { SkDebugf("%s did not expect failure\n", __FUNCTION__); REPORTER_ASSERT(reporter, 0); return false; } if (threaded && !reporter->verbose()) { return true; } SkPath pathOut, scaledPathOut; SkRegion rgnA, rgnB, openClip, rgnOut; openClip.setRect(-16000, -16000, 16000, 16000); rgnA.setPath(a, openClip); rgnB.setPath(b, openClip); rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp); rgnOut.getBoundaryPath(&pathOut); SkMatrix scale; scaleMatrix(a, b, scale); SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; SkPath scaledA, scaledB; scaledA.addPath(a, scale); scaledA.setFillType(a.getFillType()); scaledB.addPath(b, scale); scaledB.setFillType(b.getFillType()); scaledRgnA.setPath(scaledA, openClip); scaledRgnB.setPath(scaledB, openClip); scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp); scaledRgnOut.getBoundaryPath(&scaledPathOut); SkBitmap bitmap; SkPath scaledOut; scaledOut.addPath(out, scale); scaledOut.setFillType(out.getFillType()); int result = comparePaths(reporter, pathOut, scaledPathOut, out, scaledOut, bitmap, a, b, shapeOp, scale); if (result && gPathStrAssert) { REPORTER_ASSERT(reporter, 0); } reporter->bumpTestCount(); return result == 0; }
static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const char* testName, ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch) { #if 0 && DEBUG_SHOW_TEST_NAME showName(a, b, shapeOp); #endif SkPath out; if (!OpDebug(a, b, shapeOp, &out SkDEBUGPARAMS(SkipAssert::kYes == skipAssert) SkDEBUGPARAMS(testName))) { if (ExpectSuccess::kYes == expectSuccess) { SkDebugf("%s %s did not expect failure\n", __FUNCTION__, testName); REPORTER_ASSERT(reporter, 0); } return false; } else { if (ExpectSuccess::kNo == expectSuccess) { SkDebugf("%s %s unexpected success\n", __FUNCTION__, testName); REPORTER_ASSERT(reporter, 0); } } if (!reporter->verbose()) { return true; } SkPath pathOut, scaledPathOut; SkRegion rgnA, rgnB, openClip, rgnOut; openClip.setRect(-16000, -16000, 16000, 16000); rgnA.setPath(a, openClip); rgnB.setPath(b, openClip); rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp); rgnOut.getBoundaryPath(&pathOut); SkMatrix scale; scaleMatrix(a, b, scale); SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; SkPath scaledA, scaledB; scaledA.addPath(a, scale); scaledA.setFillType(a.getFillType()); scaledB.addPath(b, scale); scaledB.setFillType(b.getFillType()); scaledRgnA.setPath(scaledA, openClip); scaledRgnB.setPath(scaledB, openClip); scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp); scaledRgnOut.getBoundaryPath(&scaledPathOut); SkBitmap bitmap; SkPath scaledOut; scaledOut.addPath(out, scale); scaledOut.setFillType(out.getFillType()); int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap, a, b, shapeOp, scale, ExpectMatch::kYes == expectMatch); reporter->bumpTestCount(); return result == 0; }
void Renderable::setMatrix() { #ifdef OPENGL_ES1 glTranslatef(posx, posy, posz); glRotatef(rot, rotx, roty, rotz); glScalef(scalex, scaley, scalez); #else Mat16 tmp = translationMatrix(posx, posy, posz); currentModelViewMatrix = multiplyMatrix(currentModelViewMatrix, tmp); tmp = rotationMatrix(rot / 180 * M_PI, rotx, roty, rotz); currentModelViewMatrix = multiplyMatrix(currentModelViewMatrix, tmp); tmp = scaleMatrix(scalex, scaley, scalez); currentModelViewMatrix = multiplyMatrix(currentModelViewMatrix, tmp); glUniformMatrix4fv(shaderModelViewMatrix, 1, GL_FALSE, currentModelViewMatrix.m); glUniformMatrix3fv(shaderNormalMatrix, 1, GL_FALSE, transposedInverseMatrix9(currentModelViewMatrix).m); #endif }
Matrix generateTransform(const TwoPoints *source, const TwoPoints *dest, int reflect){ double sourceMidX = (source->x1 + source->x2)*0.5; double sourceMidY = (source->y1 + source->y2)*0.5; double destMidX = (dest->x1 + dest->x2)*0.5; double destMidY = (dest->y1 + dest->y2)*0.5; Matrix translate1 = translateMatrix(-sourceMidX, -sourceMidY); /* translate the left point to the origin */ Matrix translate2 = translateMatrix(destMidX, destMidY); /* translate the origin to the left destination */ /* compute the scale that needs to be applyed to the image */ double sdist = sqrt(SQR(source->x1 - source->x2) + SQR(source->y1 - source->y2)); double ddist = sqrt(SQR(dest->x1 - dest->x2) + SQR(dest->y1 - dest->y2)); double s = ddist/sdist; Matrix scale = scaleMatrix(s); /* compute the rotation that needs to be applyed to the image */ double stheta = atan((source->y2 -source->y1)/(source->x2 - source->x1)); double dtheta = atan((dest->y2 -dest->y1)/(dest->x2 - dest->x1)); double theta = dtheta - stheta; Matrix rotate = rotateMatrix(theta); /* compute the reflection if nessicary */ Matrix reflection = reflectMatrix(reflect,0); /* build the final transformation */ Matrix tmp1 = multiplyMatrix(scale, translate1); Matrix tmp2 = multiplyMatrix(rotate, tmp1); Matrix tmp3 = multiplyMatrix(reflection, tmp2); Matrix transform = multiplyMatrix(translate2,tmp3); /* free temporary matricies */ freeMatrix(translate1); freeMatrix(translate2); freeMatrix(scale); freeMatrix(rotate); freeMatrix(reflection); freeMatrix(tmp1); freeMatrix(tmp2); freeMatrix(tmp3); /* return final transformation */ return transform; }
void VolumeModel::bindUniformValues(QOpenGLShaderProgram * program, const Viewport::Viewport * viewport) const { program->setUniformValue(uniformValues["view"], view(viewport)); program->setUniformValue(uniformValues["model"], model(viewport)); program->setUniformValue(uniformValues["projection"], projection(viewport)); program->setUniformValue(uniformValues["lightView"], lightView(viewport)); program->setUniformValue(uniformValues["scale"], scaleMatrix()); program->setUniformValue(uniformValues["eye"], QVector4D(viewport->eye())); program->setUniformValue(uniformValues["modelBillboard"], viewport->modelBillboard()); program->setUniformValue(uniformValues["slope"], _slope); program->setUniformValue(uniformValues["intercept"], _intercept); program->setUniformValue(uniformValues["windowCenter"], _windowCenter); program->setUniformValue(uniformValues["windowWidth"], _windowWidth); program->setUniformValue(uniformValues["huRange"], _huRange); program->setUniformValue(uniformValues["valueRange"], _valueRange); }
static void test_constructor(skiatest::Reporter* reporter) { // Allocate a matrix on the heap SkMatrix44* placeholderMatrix = new SkMatrix44(SkMatrix44::kUninitialized_Constructor); SkAutoTDelete<SkMatrix44> deleteMe(placeholderMatrix); for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { placeholderMatrix->setDouble(row, col, row * col); } } // Use placement-new syntax to trigger the constructor on top of the heap // address we already initialized. This allows us to check that the // constructor did avoid initializing the matrix contents. SkMatrix44* testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kUninitialized_Constructor); REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix); REPORTER_ASSERT(reporter, !testMatrix->isIdentity()); for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { REPORTER_ASSERT(reporter, nearly_equal_double(row * col, testMatrix->getDouble(row, col))); } } // Verify that kIdentity_Constructor really does initialize to an identity matrix. testMatrix = 0; testMatrix = new(placeholderMatrix) SkMatrix44(SkMatrix44::kIdentity_Constructor); REPORTER_ASSERT(reporter, testMatrix == placeholderMatrix); REPORTER_ASSERT(reporter, testMatrix->isIdentity()); REPORTER_ASSERT(reporter, *testMatrix == SkMatrix44::I()); // Verify that that constructing from an SkMatrix initializes everything. SkMatrix44 scaleMatrix(SkMatrix44::kUninitialized_Constructor); scaleMatrix.setScale(3, 4, 5); REPORTER_ASSERT(reporter, scaleMatrix.isScale()); testMatrix = new(&scaleMatrix) SkMatrix44(SkMatrix::I()); REPORTER_ASSERT(reporter, testMatrix->isIdentity()); REPORTER_ASSERT(reporter, *testMatrix == SkMatrix44::I()); }
void SceneNode::scale(const Vector3D& amount) { Matrix4x4 s = scaleMatrix(amount); m_trans = m_trans * s; m_invtrans = s.invert() * m_invtrans; }
hstefan::math::mat4d identityMatrix() { return scaleMatrix(1.f, 1.f, 1.f); }
void ScreenSpaceImage::render() { draw(rotationMatrix() * translationMatrix() * scaleMatrix()); }
inline Matrix4f toMatrix() { return translateMatrix(position) * rotation.toMatrix() * scaleMatrix(scale); }
void DrawRoundedTriangle::execute(DrawStackArgList argList) { // set up geometry Vector2 position = *((Vector2*) argList["position"]); float rotation = *((float*) argList["rotation"]); Vector2 size = *((Vector2*) argList["size"]); float triangleHeight = cos(asin(size.x * gameGraphics->aspectRatio * 0.5f / size.y)) * size.y; float cutOutHeight = tan(asin(triangleHeight / size.y) - radians(45.0f)) * (size.x * gameGraphics->aspectRatio * 0.5f); std::vector<VertexEntry> triangleVertices; VertexEntry entry; entry.highlight = false; entry.concave = false; entry.curveOriginCoord = Vector2(0.0f, 0.0f); entry.position = Vector2(-size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); entry.primCoord = Vector2( cos(atan(triangleHeight / (size.x * (float) gameGraphics->aspectRatio / 2.0f)) + radians(90.0f)) * 2.0f, sin(atan(triangleHeight / (size.x * (float) gameGraphics->aspectRatio / 2.0f)) + radians(90.0f)) * 2.0f ); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, size.y / 2.0f); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f + (size.y - (triangleHeight - cutOutHeight))); entry.primCoord = Vector2( entry.primCoord.x / 2.0f * (2.0f - sin(atan(size.x * (float) gameGraphics->aspectRatio / 2.0f / triangleHeight)) * (triangleHeight - cutOutHeight) / size.y * 2.0f), entry.primCoord.y / 2.0f * (2.0f - sin(atan(size.x * (float) gameGraphics->aspectRatio / 2.0f / triangleHeight)) * (triangleHeight - cutOutHeight) / size.y * 2.0f) ); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, size.y / 2.0f); entry.primCoord = Vector2( -cos(atan(triangleHeight / (size.x * (float) gameGraphics->aspectRatio / 2.0f)) + radians(90.0f)) * 2.0f, sin(atan(triangleHeight / (size.x * (float) gameGraphics->aspectRatio / 2.0f)) + radians(90.0f)) * 2.0f ); triangleVertices.push_back(entry); entry.position = Vector2(size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f + (size.y - (triangleHeight - cutOutHeight))); entry.primCoord = Vector2( entry.primCoord.x / 2.0f * (2.0f - sin(atan(size.x * (float) gameGraphics->aspectRatio / 2.0f / triangleHeight)) * (triangleHeight - cutOutHeight) / size.y * 2.0f), entry.primCoord.y / 2.0f * (2.0f - sin(atan(size.x * (float) gameGraphics->aspectRatio / 2.0f / triangleHeight)) * (triangleHeight - cutOutHeight) / size.y * 2.0f) ); triangleVertices.push_back(entry); entry.curveOriginCoord = Vector2(0.0f, 1.0f); entry.position = Vector2(-size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); entry.primCoord = Vector2(-2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, 1.0f - 2.0f * cos(asin(size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y))); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f + (size.y - (triangleHeight - cutOutHeight))); entry.primCoord = Vector2(0.0f, 1.0f - 2.0f * (triangleHeight - cutOutHeight) / size.y); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f); entry.primCoord = Vector2(0.0f, -1.0f); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f); entry.primCoord = Vector2(0.0f, -1.0f); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f + (size.y - (triangleHeight - cutOutHeight))); entry.primCoord = Vector2(0.0f, 1.0f - 2.0f * (triangleHeight - cutOutHeight) / size.y); triangleVertices.push_back(entry); entry.position = Vector2(size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); entry.primCoord = Vector2(2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, 1.0f - 2.0f * cos(asin(size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y))); triangleVertices.push_back(entry); entry.position = Vector2(-size.x / 2.0f, -size.y / 2.0f); entry.primCoord = Vector2(-2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, -1.0f); triangleVertices.push_back(entry); entry.position = Vector2(-size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); entry.primCoord = Vector2(-2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, 1.0f - 2.0f * cos(asin(size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y))); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f); entry.primCoord = Vector2(0.0f, -1.0f); triangleVertices.push_back(entry); entry.position = Vector2(size.x / 2.0f, -size.y / 2.0f + (size.y - triangleHeight)); entry.primCoord = Vector2(2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, 1.0f - 2.0f * cos(asin(size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y))); triangleVertices.push_back(entry); entry.position = Vector2(size.x / 2.0f, -size.y / 2.0f); entry.primCoord = Vector2(2.0f * size.x * (float) gameGraphics->aspectRatio / 2.0f / size.y, -1.0f); triangleVertices.push_back(entry); entry.position = Vector2(0.0f, -size.y / 2.0f); entry.primCoord = Vector2(0.0f, -1.0f); triangleVertices.push_back(entry); // apply rotation Matrix4 rotationMatrix; rotationMatrix.identity(); scaleMatrix(gameGraphics->aspectRatio, 1.0f, 1.0f, rotationMatrix); rotateMatrix(Vector3(0.0f, 0.0f, 1.0f), radians(rotation), rotationMatrix); scaleMatrix(1.0f / gameGraphics->aspectRatio, 1.0f, 1.0f, rotationMatrix); for(int i = 0; i < triangleVertices.size(); ++i) { Vector4 oldPosition(triangleVertices[i].position.x, triangleVertices[i].position.y, 0.0f, 0.0f); oldPosition = oldPosition * rotationMatrix; triangleVertices[i].position = Vector2(oldPosition.x, oldPosition.y); } // update vertex buffers GLuint* triangleElementBufferArray = new GLuint[triangleVertices.size()]; for(size_t i = 0; i < triangleVertices.size(); ++i) triangleElementBufferArray[i] = i; size_t triangleVertexBufferArraySize = triangleVertices.size() * 8; GLfloat* triangleVertexBufferArray = new GLfloat[triangleVertexBufferArraySize]; for(size_t i = 0; i < triangleVertices.size(); ++i) { triangleVertexBufferArray[i * 8 + 0] = triangleVertices[i].position.x + position.x; triangleVertexBufferArray[i * 8 + 1] = triangleVertices[i].position.y + position.y; triangleVertexBufferArray[i * 8 + 2] = triangleVertices[i].primCoord.x; triangleVertexBufferArray[i * 8 + 3] = triangleVertices[i].primCoord.y; triangleVertexBufferArray[i * 8 + 4] = triangleVertices[i].curveOriginCoord.x; triangleVertexBufferArray[i * 8 + 5] = triangleVertices[i].curveOriginCoord.y; triangleVertexBufferArray[i * 8 + 6] = 2.0f - *((float*) argList["border"]) * 2.0f / (size.y / 2.0f * (float) gameGraphics->resolutionY); triangleVertexBufferArray[i * 8 + 7] = 2.0f; } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBuffers["elements"]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangleVertices.size() * sizeof(GLuint), triangleElementBufferArray, GL_STREAM_DRAW); delete[] triangleElementBufferArray; glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers["vertices"]); glBufferData(GL_ARRAY_BUFFER, triangleVertexBufferArraySize * sizeof(GLfloat), triangleVertexBufferArray, GL_STREAM_DRAW); delete[] triangleVertexBufferArray; // state glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); if(gameGraphics->supportsMultisampling) glDisable(GL_MULTISAMPLE); glDisable(GL_SCISSOR_TEST); glDisable(GL_TEXTURE_2D); // enable shader glUseProgram(gameGraphics->getProgramID("hudContainer")); // set uniforms Vector4 insideColor = *((Vector4*) argList["insideColor"]); Vector4 borderColor = *((Vector4*) argList["borderColor"]); Vector4 outsideColor = *((Vector4*) argList["outsideColor"]); glUniform4f(glGetUniformLocation(gameGraphics->getProgramID("hudContainer"), "insideColor"), insideColor.x, insideColor.y, insideColor.z, insideColor.w); glUniform4f(glGetUniformLocation(gameGraphics->getProgramID("hudContainer"), "borderColor"), borderColor.x, borderColor.y, borderColor.z, borderColor.w); glUniform4f(glGetUniformLocation(gameGraphics->getProgramID("hudContainer"), "outsideColor"), outsideColor.x, outsideColor.y, outsideColor.z, outsideColor.w); glUniform1f(glGetUniformLocation(gameGraphics->getProgramID("hudContainer"), "softEdge"), *((float*) argList["softEdge"]) * 2.0f / (size.y / 2.0f * (float) gameGraphics->resolutionY)); // draw the data stored in GPU memory glBindBuffer(GL_ARRAY_BUFFER, vertexBuffers["vertices"]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBuffers["elements"]); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "position"), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*) 0); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "primCoord"), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*) (2 * sizeof(GLfloat))); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "curveOriginCoord"), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*) (4 * sizeof(GLfloat))); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border1Dist"), 1, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*) (6 * sizeof(GLfloat))); glVertexAttribPointer(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border2Dist"), 1, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*) (7 * sizeof(GLfloat))); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "position")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "primCoord")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "curveOriginCoord")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border1Dist")); glEnableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border2Dist")); glDrawElements(GL_TRIANGLES, triangleVertices.size(), GL_UNSIGNED_INT, NULL); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "position")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "primCoord")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "curveOriginCoord")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border1Dist")); glDisableVertexAttribArray(glGetAttribLocation(gameGraphics->getProgramID("hudContainer"), "border2Dist")); }
void AtmosphereSample::RenderShadowMap(IDeviceContext *pContext, LightAttribs &LightAttribs, const float4x4 &mCameraView, const float4x4 &mCameraProj ) { ShadowMapAttribs& ShadowMapAttribs = LightAttribs.ShadowAttribs; float3 v3DirOnLight = (float3&)LightAttribs.f4DirOnLight; float3 v3LightDirection = -v3DirOnLight; // Declare working vectors float3 vLightSpaceX, vLightSpaceY, vLightSpaceZ; // Compute an inverse vector for the direction on the sun vLightSpaceZ = v3LightDirection; // And a vector for X light space vLightSpaceX = float3( 1.0f, 0.0, 0.0 ); // Compute the cross products vLightSpaceY = cross(vLightSpaceX, vLightSpaceZ); vLightSpaceX = cross(vLightSpaceZ, vLightSpaceY); // And then normalize them vLightSpaceX = normalize( vLightSpaceX ); vLightSpaceY = normalize( vLightSpaceY ); vLightSpaceZ = normalize( vLightSpaceZ ); // Declare a world to light space transformation matrix // Initialize to an identity matrix float4x4 WorldToLightViewSpaceMatr = ViewMatrixFromBasis( vLightSpaceX, vLightSpaceY, vLightSpaceZ ); ShadowMapAttribs.mWorldToLightViewT = transposeMatrix( WorldToLightViewSpaceMatr ); float3 f3CameraPosInLightSpace = m_f3CameraPos * WorldToLightViewSpaceMatr; float fMainCamNearPlane, fMainCamFarPlane; GetNearFarPlaneFromProjMatrix( mCameraProj, fMainCamNearPlane, fMainCamFarPlane, m_bIsDXDevice); for(int i=0; i < MAX_CASCADES; ++i) ShadowMapAttribs.fCascadeCamSpaceZEnd[i] = +FLT_MAX; // Render cascades for(int iCascade = 0; iCascade < m_TerrainRenderParams.m_iNumShadowCascades; ++iCascade) { auto &CurrCascade = ShadowMapAttribs.Cascades[iCascade]; float4x4 CascadeFrustumProjMatrix; float &fCascadeFarZ = ShadowMapAttribs.fCascadeCamSpaceZEnd[iCascade]; float fCascadeNearZ = (iCascade == 0) ? fMainCamNearPlane : ShadowMapAttribs.fCascadeCamSpaceZEnd[iCascade-1]; fCascadeFarZ = fMainCamFarPlane; if (iCascade < m_TerrainRenderParams.m_iNumShadowCascades-1) { float ratio = fMainCamFarPlane / fMainCamNearPlane; float power = (float)(iCascade+1) / (float)m_TerrainRenderParams.m_iNumShadowCascades; float logZ = fMainCamNearPlane * pow(ratio, power); float range = fMainCamFarPlane - fMainCamNearPlane; float uniformZ = fMainCamNearPlane + range * power; fCascadeFarZ = m_fCascadePartitioningFactor * (logZ - uniformZ) + uniformZ; } float fMaxLightShaftsDist = 3e+5f; // Ray marching always starts at the camera position, not at the near plane. // So we must make sure that the first cascade used for ray marching covers the camera position CurrCascade.f4StartEndZ.x = (iCascade == m_PPAttribs.m_iFirstCascade) ? 0 : std::min(fCascadeNearZ, fMaxLightShaftsDist); CurrCascade.f4StartEndZ.y = std::min(fCascadeFarZ, fMaxLightShaftsDist); CascadeFrustumProjMatrix = mCameraProj; SetNearFarClipPlanes( CascadeFrustumProjMatrix, fCascadeNearZ, fCascadeFarZ, m_bIsDXDevice ); float4x4 CascadeFrustumViewProjMatr = mCameraView * CascadeFrustumProjMatrix; float4x4 CascadeFrustumProjSpaceToWorldSpace = inverseMatrix(CascadeFrustumViewProjMatr); float4x4 CascadeFrustumProjSpaceToLightSpace = CascadeFrustumProjSpaceToWorldSpace * WorldToLightViewSpaceMatr; // Set reference minimums and maximums for each coordinate float3 f3MinXYZ(f3CameraPosInLightSpace), f3MaxXYZ(f3CameraPosInLightSpace); // First cascade used for ray marching must contain camera within it if( iCascade != m_PPAttribs.m_iFirstCascade ) { f3MinXYZ = float3(+FLT_MAX, +FLT_MAX, +FLT_MAX); f3MaxXYZ = float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); } for(int iClipPlaneCorner=0; iClipPlaneCorner < 8; ++iClipPlaneCorner) { float3 f3PlaneCornerProjSpace( (iClipPlaneCorner & 0x01) ? +1.f : - 1.f, (iClipPlaneCorner & 0x02) ? +1.f : - 1.f, // Since we use complimentary depth buffering, // far plane has depth 0 (iClipPlaneCorner & 0x04) ? 1.f : (m_bIsDXDevice ? 0.f : -1.f)); float3 f3PlaneCornerLightSpace = f3PlaneCornerProjSpace * CascadeFrustumProjSpaceToLightSpace; f3MinXYZ = min(f3MinXYZ, f3PlaneCornerLightSpace); f3MaxXYZ = max(f3MaxXYZ, f3PlaneCornerLightSpace); } // It is necessary to ensure that shadow-casting patches, which are not visible // in the frustum, are still rendered into the shadow map f3MinXYZ.z -= AirScatteringAttribs().fEarthRadius * sqrt(2.f); // Align cascade extent to the closest power of two float fShadowMapDim = (float)m_uiShadowMapResolution; float fCascadeXExt = (f3MaxXYZ.x - f3MinXYZ.x) * (1 + 1.f/fShadowMapDim); float fCascadeYExt = (f3MaxXYZ.y - f3MinXYZ.y) * (1 + 1.f/fShadowMapDim); const float fExtStep = 2.f; fCascadeXExt = pow( fExtStep, ceil( log(fCascadeXExt)/log(fExtStep) ) ); fCascadeYExt = pow( fExtStep, ceil( log(fCascadeYExt)/log(fExtStep) ) ); // Align cascade center with the shadow map texels to alleviate temporal aliasing float fCascadeXCenter = (f3MaxXYZ.x + f3MinXYZ.x)/2.f; float fCascadeYCenter = (f3MaxXYZ.y + f3MinXYZ.y)/2.f; float fTexelXSize = fCascadeXExt / fShadowMapDim; float fTexelYSize = fCascadeXExt / fShadowMapDim; fCascadeXCenter = floor(fCascadeXCenter/fTexelXSize) * fTexelXSize; fCascadeYCenter = floor(fCascadeYCenter/fTexelYSize) * fTexelYSize; // Compute new cascade min/max xy coords f3MaxXYZ.x = fCascadeXCenter + fCascadeXExt/2.f; f3MinXYZ.x = fCascadeXCenter - fCascadeXExt/2.f; f3MaxXYZ.y = fCascadeYCenter + fCascadeYExt/2.f; f3MinXYZ.y = fCascadeYCenter - fCascadeYExt/2.f; CurrCascade.f4LightSpaceScale.x = 2.f / (f3MaxXYZ.x - f3MinXYZ.x); CurrCascade.f4LightSpaceScale.y = 2.f / (f3MaxXYZ.y - f3MinXYZ.y); CurrCascade.f4LightSpaceScale.z = (m_bIsDXDevice ? 1.f : 2.f) / (f3MaxXYZ.z - f3MinXYZ.z); // Apply bias to shift the extent to [-1,1]x[-1,1]x[0,1] for DX or to [-1,1]x[-1,1]x[-1,1] for GL // Find bias such that f3MinXYZ -> (-1,-1,0) for DX or (-1,-1,-1) for GL CurrCascade.f4LightSpaceScaledBias.x = -f3MinXYZ.x * CurrCascade.f4LightSpaceScale.x - 1.f; CurrCascade.f4LightSpaceScaledBias.y = -f3MinXYZ.y * CurrCascade.f4LightSpaceScale.y - 1.f; CurrCascade.f4LightSpaceScaledBias.z = -f3MinXYZ.z * CurrCascade.f4LightSpaceScale.z + (m_bIsDXDevice ? 0.f : -1.f); float4x4 ScaleMatrix = scaleMatrix( CurrCascade.f4LightSpaceScale.x, CurrCascade.f4LightSpaceScale.y, CurrCascade.f4LightSpaceScale.z ); float4x4 ScaledBiasMatrix = translationMatrix( CurrCascade.f4LightSpaceScaledBias.x, CurrCascade.f4LightSpaceScaledBias.y, CurrCascade.f4LightSpaceScaledBias.z ) ; // Note: bias is applied after scaling! float4x4 CascadeProjMatr = ScaleMatrix * ScaledBiasMatrix; //D3DXMatrixOrthoOffCenterLH( &m_LightOrthoMatrix, MinX, MaxX, MinY, MaxY, MaxZ, MinZ); // Adjust the world to light space transformation matrix float4x4 WorldToLightProjSpaceMatr = WorldToLightViewSpaceMatr * CascadeProjMatr; float4x4 ProjToUVScale, ProjToUVBias; if( m_bIsDXDevice ) { ProjToUVScale = scaleMatrix( 0.5f, -0.5f, 1.f ); ProjToUVBias = translationMatrix( 0.5f, 0.5f, 0.f ); } else { ProjToUVScale = scaleMatrix( 0.5f, 0.5f, 0.5f ); ProjToUVBias = translationMatrix( 0.5f, 0.5f, 0.5f ); } float4x4 WorldToShadowMapUVDepthMatr = WorldToLightProjSpaceMatr * ProjToUVScale * ProjToUVBias; ShadowMapAttribs.mWorldToShadowMapUVDepthT[iCascade] = transposeMatrix( WorldToShadowMapUVDepthMatr ); m_pImmediateContext->SetRenderTargets( 0, nullptr, m_pShadowMapDSVs[iCascade] ); m_pImmediateContext->ClearDepthStencil( m_pShadowMapDSVs[iCascade], CLEAR_DEPTH_FLAG, 1.f ); // Render terrain to shadow map { MapHelper<CameraAttribs> CamAttribs( m_pImmediateContext, m_pcbCameraAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); CamAttribs->mViewProjT = transposeMatrix( WorldToLightProjSpaceMatr ); } m_EarthHemisphere.Render(m_pImmediateContext, m_TerrainRenderParams, m_f3CameraPos, WorldToLightProjSpaceMatr, nullptr, nullptr, nullptr, true); } pContext->SetRenderTargets( 0, nullptr, nullptr ); }
dgPolygonMeshDesc::dgPolygonMeshDesc(dgCollisionParamProxy& proxy, void* const userData) :dgFastAABBInfo() ,m_boxDistanceTravelInMeshSpace(dgFloat32 (0.0f)) ,m_threadNumber(proxy.m_threadIndex) ,m_faceCount(0) ,m_vertexStrideInBytes(0) ,m_skinThickness(proxy.m_skinThickness) ,m_userData (userData) ,m_objBody (proxy.m_referenceBody) ,m_polySoupBody(proxy.m_floatingBody) ,m_objCollision(proxy.m_referenceCollision) ,m_polySoupCollision(proxy.m_floatingCollision) ,m_vertex(NULL) ,m_faceIndexCount(NULL) ,m_faceVertexIndex(NULL) ,m_faceIndexStart(NULL) ,m_hitDistance(NULL) ,m_maxT(dgFloat32 (1.0f)) ,m_doContinuesCollisionTest(proxy.m_continueCollision) { dgAssert (m_polySoupCollision->IsType (dgCollision::dgCollisionMesh_RTTI)); dgAssert (m_objCollision->IsType (dgCollision::dgCollisionConvexShape_RTTI)); const dgMatrix& hullMatrix = m_objCollision->GetGlobalMatrix(); const dgMatrix& soupMatrix = m_polySoupCollision->GetGlobalMatrix(); proxy.m_matrix = hullMatrix * soupMatrix.Inverse(); switch (m_objCollision->GetCombinedScaleType(m_polySoupCollision->GetScaleType())) { case dgCollisionInstance::m_unit: { dgMatrix& matrix = *this; matrix = proxy.m_matrix; SetTransposeAbsMatrix (matrix); const dgCollision* const collision = m_objCollision->GetChildShape(); m_objCollision->CalcAABB (*this, m_p0, m_p1); m_posit += matrix.RotateVector (collision->GetObbOrigin()); m_size = collision->GetObbSize() + dgCollisionInstance::m_padding; break; } case dgCollisionInstance::m_uniform: { dgMatrix& matrix = *this; matrix = proxy.m_matrix; const dgVector& meshInvScale = m_polySoupCollision->GetInvScale(); matrix.m_posit = matrix.m_posit.CompProduct4(meshInvScale) | dgVector::m_wOne; SetTransposeAbsMatrix (matrix); dgMatrix scaleMatrix (meshInvScale.CompProduct4(m_front), meshInvScale.CompProduct4(m_up), meshInvScale.CompProduct4(m_right), m_posit); m_objCollision->CalcAABB (scaleMatrix, m_p0, m_p1); dgVector scale (m_objCollision->GetScale().CompProduct4(m_polySoupCollision->GetInvScale())); const dgCollision* const collision = m_objCollision->GetChildShape(); m_posit += matrix.RotateVector (collision->GetObbOrigin().CompProduct4(scale)); m_size = collision->GetObbSize().CompProduct4(scale) + dgCollisionInstance::m_padding; break; } case dgCollisionInstance::m_nonUniform: { dgMatrix& matrix = *this; matrix = proxy.m_matrix; const dgVector& meshInvScale = m_polySoupCollision->GetInvScale(); matrix.m_posit = matrix.m_posit.CompProduct4(meshInvScale) | dgVector::m_wOne; SetTransposeAbsMatrix (matrix); dgMatrix scaleMatrix (meshInvScale.CompProduct4(m_front), meshInvScale.CompProduct4(m_up), meshInvScale.CompProduct4(m_right), m_posit); m_objCollision->CalcAABB (scaleMatrix, m_p0, m_p1); const dgCollision* const collision = m_objCollision->GetChildShape(); dgMatrix obbScaledMatrix (scaleMatrix * matrix.Inverse()); dgVector obbP0; dgVector obbP1; m_objCollision->CalcAABB (obbScaledMatrix, obbP0, obbP1); m_size = (obbP1 - obbP0).CompProduct4(dgVector::m_half); m_posit += matrix.RotateVector ((obbP1 + obbP0).CompProduct4(dgVector::m_half)); break; } default: { dgAssert (0); } } }
inline Matrix4f getView() const { return scaleMatrix( {transform.scale.x, transform.scale.y, transform.scale.z}) * transform.rotation.toMatrix() * translateMatrix(-transform.position); }
//! Apply a scale transformation to the matrix Matrix4& scale(T const& x, T const& y, T const& z=1) { Matrix4 tmp = scaleMatrix(x, y, z); tmp *= *this; *this = tmp; return (*this); }
void downloadCalibration(unsigned int index) { /* Open a Kinect camera: */ Kinect::Camera camera(usbContext,index); std::cout<<"Downloading factory calibration data for Kinect "<<camera.getSerialNumber()<<"..."<<std::endl; /* Retrieve the factory calibration data: */ Kinect::Camera::CalibrationParameters cal; camera.getCalibrationParameters(cal); /* Calculate the depth-to-distance conversion formula: */ double numerator=10.0*(4.0*cal.dcmosEmitterDist*cal.referenceDistance)/cal.referencePixelSize; double denominator=4.0*cal.dcmosEmitterDist/cal.referencePixelSize+4.0*cal.constantShift+1.5; std::cout<<"Depth conversion formula: dist[mm] = "<<numerator<<" / ("<<denominator<<" - depth)"<<std::endl; /* Calculate the depth pixel unprojection matrix: */ double scale=2.0*cal.referencePixelSize/cal.referenceDistance; Math::Matrix depthMatrix(4,4,0.0); depthMatrix(0,0)=scale; depthMatrix(0,3)=-scale*640.0/2.0; depthMatrix(1,1)=scale; depthMatrix(1,3)=-scale*480.0/2.0; depthMatrix(2,3)=-1.0; depthMatrix(3,2)=-1.0/numerator; depthMatrix(3,3)=denominator/numerator; { std::cout<<std::endl<<"Depth unprojection matrix:"<<std::endl; std::streamsize oldPrec=std::cout.precision(8); std::cout.setf(std::ios::fixed); for(int i=0;i<4;++i) { std::cout<<" "; for(int j=0;j<4;++j) std::cout<<' '<<std::setw(11)<<depthMatrix(i,j); std::cout<<std::endl; } std::cout.unsetf(std::ios::fixed); std::cout.precision(oldPrec); } /* Calculate the depth-to-color mapping: */ double colorShiftA=cal.dcmosRcmosDist/(cal.referencePixelSize*2.0)+0.375; double colorShiftB=cal.dcmosRcmosDist*cal.referenceDistance*10.0/(cal.referencePixelSize*2.0); std::cout<<"Depth-to-color pixel shift formula: Shift = "<<colorShiftA<<" - "<<colorShiftB<<"/dist[mm]"<<std::endl; /* Formula to go directly from depth to displacement: */ double dispA=colorShiftA-colorShiftB*denominator/numerator; double dispB=colorShiftB/numerator; std::cout<<"Or: Shift = "<<dispA<<" + "<<dispB<<"*depth"<<std::endl; /* Tabulate the bivariate pixel mapping polynomial using forward differencing: */ double* colorx=new double[640*480]; double* colory=new double[640*480]; double ax=cal.ax; double bx=cal.bx; double cx=cal.cx; double dx=cal.dx; double ay=cal.ay; double by=cal.by; double cy=cal.cy; double dy=cal.dy; double dx0=(cal.dxStart<<13)>>4; double dy0=(cal.dyStart<<13)>>4; double dxdx0=(cal.dxdxStart<<11)>>3; double dxdy0=(cal.dxdyStart<<11)>>3; double dydx0=(cal.dydxStart<<11)>>3; double dydy0=(cal.dydyStart<<11)>>3; double dxdxdx0=(cal.dxdxdxStart<<5)<<3; double dydxdx0=(cal.dydxdxStart<<5)<<3; double dxdxdy0=(cal.dxdxdyStart<<5)<<3; double dydxdy0=(cal.dydxdyStart<<5)<<3; double dydydx0=(cal.dydydxStart<<5)<<3; double dydydy0=(cal.dydydyStart<<5)<<3; for(int y=0;y<480;++y) { dxdxdx0+=cx; dxdx0 +=dydxdx0/256.0; dydxdx0+=dx; dx0 +=dydx0/64.0; dydx0 +=dydydx0/256.0; dydydx0+=bx; dxdxdy0+=cy; dxdy0 +=dydxdy0/256.0; dydxdy0+=dy; dy0 +=dydy0/64.0; dydy0 +=dydydy0/256.0; dydydy0+=by; double coldxdxdy=dxdxdy0; double coldxdy=dxdy0; double coldy=dy0; double coldxdxdx=dxdxdx0; double coldxdx=dxdx0; double coldx=dx0; for(int x=0;x<640;++x) { colorx[y*640+x]=double(x)+coldx/131072.0+1.0; colory[y*640+x]=double(y)+coldy/131072.0+1.0; #if 0 if(x%40==20&&y%40==20) std::cout<<x<<", "<<y<<": "<<colorx[y*640+x]<<", "<<colory[y*640+x]<<std::endl; #endif coldx+=coldxdx/64.0; coldxdx+=coldxdxdx/256.0; coldxdxdx+=ax; coldy+=coldxdy/64.0; coldxdy+=coldxdxdy/256.0; coldxdxdy+=ay; } } /* Calculate the texture projection matrix by sampling the pixel mapping polynomial: */ int minDepth=Math::ceil(denominator-numerator/500.0); // 500mm is minimum viewing distance int maxDepth=Math::ceil(denominator-numerator/3000.0); // 3000mm is maximum reasonable viewing distance std::cout<<"Calculating best-fit color projection matrix for depth value range "<<minDepth<<" - "<<maxDepth<<"..."<<std::endl; Math::Matrix colorSystem(12,12,0.0); Math::Matrix depthPoint(4,1,0.0); depthPoint(3)=1.0; for(int y=20;y<480;y+=40) { depthPoint(1)=(double(y)+0.5)/480.0; for(int x=20;x<640;x+=40) { depthPoint(0)=(double(x)+0.5)/640.0; for(int depth=minDepth;depth<=maxDepth;depth+=20) { /* Transform the depth point to color image space using the non-linear transformation: */ // int xdisp=x+Math::floor(dispA+dispB*double(depth)+0.5); // if(xdisp>=0&&xdisp<640) { // double colX=double(xdisp)/640.0; // double colY=double(y)/480.0; // double colX=colorx[(479-y)*640+xdisp]/640.0; // double colY=(479.0-colory[(479-y)*640+xdisp])/480.0; double colX=(colorx[(479-y)*640+x]+dispA+dispB*double(depth))/640.0; double colY=(479.0-colory[(479-y)*640+x])/480.0; /* Calculate the 3D point based on the depth unprojection matrix: */ depthPoint(2)=double(depth)/double(maxDepth); Math::Matrix worldPoint=depthMatrix*depthPoint; /* Make the world point affine: */ for(int i=0;i<3;++i) worldPoint(i)/=worldPoint(3); /* Enter the world point / color point pair into the color projection system: */ double eq[2][12]; eq[0][0]=depthPoint(0); eq[0][1]=depthPoint(1); eq[0][2]=depthPoint(2); eq[0][3]=1.0; eq[0][4]=0.0; eq[0][5]=0.0; eq[0][6]=0.0; eq[0][7]=0.0; eq[0][8]=-colX*depthPoint(0); eq[0][9]=-colX*depthPoint(1); eq[0][10]=-colX*depthPoint(2); eq[0][11]=-colX; eq[1][0]=0.0; eq[1][1]=0.0; eq[1][2]=0.0; eq[1][3]=0.0; eq[1][4]=depthPoint(0); eq[1][5]=depthPoint(1); eq[1][6]=depthPoint(2); eq[1][7]=1.0; eq[1][8]=-colY*depthPoint(0); eq[1][9]=-colY*depthPoint(1); eq[1][10]=-colY*depthPoint(2); eq[1][11]=-colY; for(int row=0;row<2;++row) for(unsigned int i=0;i<12;++i) for(unsigned int j=0;j<12;++j) colorSystem(i,j)+=eq[row][i]*eq[row][j]; } } } } /* Find the linear system's smallest eigenvalue: */ std::pair<Math::Matrix,Math::Matrix> qe=colorSystem.jacobiIteration(); unsigned int minEIndex=0; double minE=Math::abs(qe.second(0,0)); for(unsigned int i=1;i<12;++i) { if(minE>Math::abs(qe.second(i,0))) { minEIndex=i; minE=Math::abs(qe.second(i,0)); } } std::cout<<"Smallest eigenvalue of color system = "<<minE<<std::endl; /* Create the normalized homography and extend it to a 4x4 matrix: */ Math::Matrix colorMatrix(4,4); double cmScale=qe.first(11,minEIndex); for(int i=0;i<2;++i) for(int j=0;j<4;++j) colorMatrix(i,j)=qe.first(i*4+j,minEIndex)/cmScale; for(int j=0;j<4;++j) colorMatrix(2,j)=j==2?1.0:0.0; for(int j=0;j<4;++j) colorMatrix(3,j)=qe.first(2*4+j,minEIndex)/cmScale; /* Un-normalize the color matrix: */ for(int i=0;i<4;++i) { colorMatrix(i,0)/=640.0; colorMatrix(i,1)/=480.0; colorMatrix(i,2)/=double(maxDepth); } /* Calculate the approximation error: */ double rms=0.0; unsigned int numPoints=0; depthPoint(3)=1.0; for(int y=20;y<480;y+=40) { depthPoint(1)=double(y)+0.5; for(int x=20;x<640;x+=40) { depthPoint(0)=double(x)+0.5; for(int depth=minDepth;depth<=maxDepth;depth+=20) { /* Transform the depth point to color image space using the non-linear transformation: */ // int xdisp=x+Math::floor(dispA+dispB*double(depth)+0.5); // if(xdisp>=0&&xdisp<640) { // double colX=double(xdisp)/640.0; // double colY=double(y)/480.0; // double colX=colorx[y*640+xdisp]/640.0; // double colY=(colory[y*640+xdisp]-50.0)/480.0; double colX=(colorx[y*640+x]+dispA+dispB*double(depth))/640.0; double colY=(colory[y*640+x]-0.0)/480.0; /* Transform the depth image point to color space using the color matrix: */ depthPoint(2)=double(depth); Math::Matrix colorPoint=colorMatrix*depthPoint; /* Calculate the approximation error: */ double dist=Math::sqr(colorPoint(0)/colorPoint(3)-colX)+Math::sqr(colorPoint(1)/colorPoint(3)-colY); rms+=dist; ++numPoints; } } } } /* Print the RMS: */ std::cout<<"Color matrix approximation RMS = "<<Math::sqrt(rms/double(numPoints))<<std::endl; /* Make the color matrix compatible with Kinect::Projector's way of doing things: */ // colorMatrix*=depthMatrix; { std::cout<<"Optimal homography from world space to color image space:"<<std::endl; std::streamsize oldPrec=std::cout.precision(8); std::cout.setf(std::ios::fixed); for(int i=0;i<4;++i) { std::cout<<" "; for(int j=0;j<4;++j) std::cout<<' '<<std::setw(11)<<colorMatrix(i,j); std::cout<<std::endl; } std::cout.unsetf(std::ios::fixed); std::cout.precision(oldPrec); } delete[] colorx; delete[] colory; /* Convert the depth matrix from mm to cm: */ Math::Matrix scaleMatrix(4,4,1.0); for(int i=0;i<3;++i) scaleMatrix(i,i)=0.1; depthMatrix=scaleMatrix*depthMatrix; /* Write the depth and color matrices to an intrinsic parameter file: */ std::string calibFileName=KINECT_CONFIG_DIR; calibFileName.push_back('/'); calibFileName.append(KINECT_CAMERA_INTRINSICPARAMETERSFILENAMEPREFIX); calibFileName.push_back('-'); calibFileName.append(camera.getSerialNumber()); calibFileName.append(".dat"); if(!Misc::doesPathExist(calibFileName.c_str())) { std::cout<<"Writing full intrinsic camera parameters to "<<calibFileName<<std::endl; IO::FilePtr calibFile=IO::openFile(calibFileName.c_str(),IO::File::WriteOnly); calibFile->setEndianness(Misc::LittleEndian); for(int i=0;i<4;++i) for(int j=0;j<4;++j) calibFile->write<double>(depthMatrix(i,j)); for(int i=0;i<4;++i) for(int j=0;j<4;++j) calibFile->write<double>(colorMatrix(i,j)); } else std::cout<<"Intrinsic camera parameter file "<<calibFileName<<" already exists"<<std::endl; }