//===================================================================== bool MouseBoxZoomer::eventFilter(QObject *widget, QEvent *e) { GlMainWidget *glw = static_cast<GlMainWidget *>(widget); GlGraphInputData *inputData = glw->getScene()->getGlGraphComposite()->getInputData(); if (e->type() == QEvent::MouseButtonPress) { QMouseEvent * qMouseEv = static_cast<QMouseEvent *>(e); if (qMouseEv->buttons() == mButton && (kModifier == Qt::NoModifier || qMouseEv->modifiers() & kModifier)) { if (!started) { x = qMouseEv->x(); y = glw->height() - qMouseEv->y(); w = 0; h = 0; started = true; graph = inputData->getGraph(); } else { if (inputData->getGraph() != graph) { graph = NULL; started = false; } } return true; } if (qMouseEv->buttons()==Qt::MidButton) { started = false; glw->redraw(); return true; } return false; } if (e->type() == QEvent::MouseMove) { QMouseEvent * qMouseEv = static_cast<QMouseEvent *>(e); if ((qMouseEv->buttons() & mButton) && (kModifier == Qt::NoModifier || qMouseEv->modifiers() & kModifier)) { if (inputData->getGraph() != graph) { graph = NULL; started = false; } if (started) { if ((qMouseEv->x() > 0) && (qMouseEv->x() < glw->width())) w = qMouseEv->x() - x; if ((qMouseEv->y() > 0) && (qMouseEv->y() < glw->height())) h = y - (glw->height() - qMouseEv->y()); glw->redraw(); return true; } } } if (e->type() == QEvent::MouseButtonDblClick) { GlBoundingBoxSceneVisitor bbVisitor(inputData); glw->getScene()->getLayer("Main")->acceptVisitor(&bbVisitor); QtGlSceneZoomAndPanAnimator zoomAnPan(glw, bbVisitor.getBoundingBox()); zoomAnPan.animateZoomAndPan(); return true; } if (e->type() == QEvent::MouseButtonRelease) { QMouseEvent * qMouseEv = static_cast<QMouseEvent *>(e); if ((qMouseEv->button() == mButton && (kModifier == Qt::NoModifier || qMouseEv->modifiers() & kModifier))) { if (inputData->getGraph() != graph) { graph = NULL; started = false; } if (started) { started = false; if(!(w==0 && h==0)) { int width = glw->width(); int height = glw->height(); Coord bbMin(width-x, height - y+h); Coord bbMax(width-(x+w), height - y); if (abs(bbMax[0] - bbMin[0]) > 1 && abs(bbMax[1] - bbMin[1]) > 1) { BoundingBox sceneBB; sceneBB.expand(glw->getScene()->getGraphCamera().viewportTo3DWorld(glw->screenToViewport(bbMin))); sceneBB.expand(glw->getScene()->getGraphCamera().viewportTo3DWorld(glw->screenToViewport(bbMax))); QtGlSceneZoomAndPanAnimator zoomAnPan(glw, sceneBB); zoomAnPan.animateZoomAndPan(); } } } return true; } } return false; }
void BoundingSphere::merge(const BoundingBox& box) { if (box.isEmpty()) return; const Vector3& min = box.min; const Vector3& max = box.max; // Find the corner of the bounding box that is farthest away from this sphere's center. float v1x = min.x - center.x; float v1y = min.y - center.y; float v1z = min.z - center.z; float v2x = max.x - center.x; float v2y = max.y - center.y; float v2z = max.z - center.z; float fx = min.x; float fy = min.y; float fz = min.z; if (v2x > v1x) { fx = max.x; } if (v2y > v1y) { fy = max.y; } if (v2z > v1z) { fz = max.z; } // Calculate the unit vector and the distance between the center and the farthest point. v1x = center.x - fx; v1y = center.y - fy; v1z = center.z - fz; float distance = sqrt(v1x * v1x + v1y * v1y + v1z * v1z); // If the box is inside the sphere, we are done. if (distance <= radius) { return; } // Calculate the unit vector between the center and the farthest point. GP_ASSERT(distance != 0.0f); float dI = 1.0f / distance; v1x *= dI; v1y *= dI; v1z *= dI; // Calculate the new radius. float r = (radius + distance) * 0.5f; // Calculate the new center. v1x = v1x * r + fx; v1y = v1y * r + fy; v1z = v1z * r + fz; // Set the new center and radius. center.x = v1x; center.y = v1y; center.z = v1z; radius = r; }
void WriteVertex(float*& dest, aiMesh* mesh, unsigned index, unsigned elementMask, BoundingBox& box, const Matrix3x4& vertexTransform, const Matrix3& normalTransform, Vector<PODVector<unsigned char> >& blendIndices, Vector<PODVector<float> >& blendWeights) { Vector3 vertex = vertexTransform * ToVector3(mesh->mVertices[index]); box.Merge(vertex); *dest++ = vertex.x_; *dest++ = vertex.y_; *dest++ = vertex.z_; if (elementMask & MASK_NORMAL) { Vector3 normal = normalTransform * ToVector3(mesh->mNormals[index]); *dest++ = normal.x_; *dest++ = normal.y_; *dest++ = normal.z_; } if (elementMask & MASK_COLOR) { *((unsigned*)dest) = Color(mesh->mColors[0][index].r, mesh->mColors[0][index].g, mesh->mColors[0][index].b, mesh->mColors[0][index].a).ToUInt(); ++dest; } if (elementMask & MASK_TEXCOORD1) { Vector3 texCoord = ToVector3(mesh->mTextureCoords[0][index]); *dest++ = texCoord.x_; *dest++ = texCoord.y_; } if (elementMask & MASK_TEXCOORD2) { Vector3 texCoord = ToVector3(mesh->mTextureCoords[1][index]); *dest++ = texCoord.x_; *dest++ = texCoord.y_; } if (elementMask & MASK_TANGENT) { Vector3 tangent = normalTransform * ToVector3(mesh->mTangents[index]); Vector3 normal = normalTransform * ToVector3(mesh->mNormals[index]); Vector3 bitangent = normalTransform * ToVector3(mesh->mBitangents[index]); // Check handedness float w = 1.0f; if ((tangent.CrossProduct(normal)).DotProduct(bitangent) < 0.5f) w = -1.0f; *dest++ = tangent.x_; *dest++ = tangent.y_; *dest++ = tangent.z_; *dest++ = w; } if (elementMask & MASK_BLENDWEIGHTS) { for (unsigned i = 0; i < 4; ++i) { if (i < blendWeights[index].Size()) *dest++ = blendWeights[index][i]; else *dest++ = 0.0f; } } if (elementMask & MASK_BLENDINDICES) { unsigned char* destBytes = (unsigned char*)dest; ++dest; for (unsigned i = 0; i < 4; ++i) { if (i < blendIndices[index].Size()) *destBytes++ = blendIndices[index][i]; else *destBytes++ = 0; } } }
BoundingBox MinimumBoundingBox::getMinimumBoundingBox(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud) { BoundingBox bb; std::vector< pcl::Vertices > polygons; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZRGB>); pcl::ConvexHull<pcl::PointXYZRGB> chull; chull.setInputCloud (cloud); chull.setDimension(3); chull.reconstruct (*cloud_hull,polygons); yarp::sig::Vector x1; yarp::sig::Vector x2; yarp::sig::Vector x3; yarp::sig::Vector y1; yarp::sig::Vector y2; yarp::sig::Vector y3; yarp::sig::Vector z1; yarp::sig::Vector z2; yarp::sig::Vector z3; for (int i=0; i<polygons.size(); i++) { pcl::Vertices vertex=polygons.at(i); x1.push_back(cloud_hull->at(vertex.vertices[0]).x); x2.push_back(cloud_hull->at(vertex.vertices[1]).x); x3.push_back(cloud_hull->at(vertex.vertices[2]).x); y1.push_back(cloud_hull->at(vertex.vertices[0]).y); y2.push_back(cloud_hull->at(vertex.vertices[1]).y); y3.push_back(cloud_hull->at(vertex.vertices[2]).y); z1.push_back(cloud_hull->at(vertex.vertices[0]).z); z2.push_back(cloud_hull->at(vertex.vertices[1]).z); z3.push_back(cloud_hull->at(vertex.vertices[2]).z); } Matrix pointCloud(cloud_hull->size(),3); for (int i=0; i<cloud_hull->size(); i++) { pointCloud(i,0)=cloud_hull->at(i).x; pointCloud(i,1)=cloud_hull->at(i).y; pointCloud(i,2)=cloud_hull->at(i).z; } yarp::sig::Vector v1x=x2-x1; yarp::sig::Vector v1y=y2-y1; yarp::sig::Vector v1z=z2-z1; std::vector<yarp::sig::Vector> edges1; retrieveEdges(v1x,v1y,v1z,edges1); yarp::sig::Vector v2x=x3-x1; yarp::sig::Vector v2y=y3-y1; yarp::sig::Vector v2z=z3-z1; std::vector<yarp::sig::Vector> edges2; retrieveEdges2(v2x,v2y,v2z,edges1,edges2); std::vector<yarp::sig::Vector> crossProduct; for (int i=0; i<edges1.size(); i++) { yarp::sig::Vector vect=cross(edges1.at(i),edges2.at(i)); crossProduct.push_back(vect); } yarp::sig::Vector alpha; yarp::sig::Vector beta; yarp::sig::Vector gamma; eulerAngles(edges1, edges2, crossProduct, alpha, beta, gamma); Matrix minmax(2,3); double minVol=100000; Matrix rot2; for (int i=0; i<alpha.size(); i++) { Matrix rot; buildRotMat3(alpha[i],beta[i],gamma[i],rot); Matrix xyz_i=pointCloud*rot; findRotation(xyz_i,rot2); Matrix rot3dim=eye(3,3); rot3dim.setSubmatrix(rot2,0,0); Matrix rotation=rot*rot3dim; xyz_i=pointCloud*rotation; yarp::sig::Vector minimum; Helpers::min(xyz_i,minimum); yarp::sig::Vector maximum; Helpers::max(xyz_i,maximum); yarp::sig::Vector h=maximum-minimum; double prod=h[0]*h[1]*h[2]; if (prod<minVol) { minVol=prod; bb.setOrientation(rotation); minmax.setRow(0,minimum); minmax.setRow(1,maximum); } } Matrix cornerpointsTmp(8,3); assignCorners(minmax,cornerpointsTmp); Matrix cornerpoints=cornerpointsTmp*(bb.getOrientation().transposed()); std::vector<iCub::data3D::PointXYZ> corners; for (unsigned int i=0; i<cornerpoints.rows(); i++) corners.push_back(PointXYZ(cornerpoints(i,0),cornerpoints(i,1),cornerpoints(i,2))); bb.setCorners(corners); return bb; }
bool Collider::Check(const BoundingBox &BB, const Sphere &SP) { real dmin = 0.0; if(SP.position.x < BB.Mininmum(X)) { dmin += ((SP.position.x - BB.Mininmum(X))*(SP.position.x - BB.Mininmum(X))) ; } else if (SP.position.x > BB.Mininmum(X)) { dmin += ((SP.position.x - BB.Mininmum(X))*(SP.position.x - BB.Maximum(X))) ; } if(SP.position.x < BB.Mininmum(X)) { dmin += ((SP.position.x - BB.Mininmum(X))*(SP.position.x - BB.Mininmum(X))) ; } else if (SP.position.x > BB.Mininmum(X)) { dmin += ((SP.position.x - BB.Mininmum(X))*(SP.position.x - BB.Maximum(X))) ; } if(SP.position.y < BB.Mininmum(Y)) { dmin += ((SP.position.y - BB.Mininmum(Y))*(SP.position.y - BB.Mininmum(Y))) ; } else if (SP.position.y > BB.Mininmum(Y)) { dmin += ((SP.position.y - BB.Mininmum(Y))*(SP.position.y - BB.Maximum(Y))) ; } if(SP.position.z < BB.Mininmum(Z)) { dmin += ((SP.position.z - BB.Mininmum(Z))*(SP.position.z - BB.Mininmum(Z))) ; } else if (SP.position.z > BB.Mininmum(Z)) { dmin += ((SP.position.z - BB.Mininmum(Z))*(SP.position.z - BB.Maximum(Z))) ; } return dmin <= (SP.radious*SP.radious); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool ShaderUniforms::onInitialize() { m_propGlobalUniformSet = new PropertyBool("Use global uniform set", true); m_propertyPublisher->publishProperty(m_propGlobalUniformSet.p()); // Create the single shader program with default uniforms ref<ShaderProgram> shaderProg; { ShaderProgramGenerator shaderGen("ShaderUniforms", ShaderSourceProvider::instance()); shaderGen.addVertexCodeFromFile("ShaderUniforms_Vert"); shaderGen.addFragmentCode(ShaderSourceRepository::light_SimpleHeadlight); shaderGen.addFragmentCodeFromFile("ShaderUniforms_Frag"); shaderProg = shaderGen.generate(); shaderProg->setDefaultUniform(new UniformFloat("u_color0", Color3f(Color3::WHITE))); shaderProg->setDefaultUniform(new UniformFloat("u_color1", Color3f(Color3::MAGENTA))); shaderProg->setDefaultUniform(new UniformFloat("u_colorMixFactor", 1.0f)); } // No uniforms, relies only on the shader program defaults m_effNoUniforms = new Effect; m_effNoUniforms->setShaderProgram(shaderProg.p()); // Effect with only mix factor set (uses colors from default) m_effWithSomeUniforms = new Effect; m_effWithSomeUniforms->setShaderProgram(shaderProg.p()); m_effWithSomeUniforms->setUniform(new UniformFloat("u_colorMixFactor", 0)); // Fully specified uniforms m_effWithAllUniforms = new Effect; m_effWithAllUniforms->setShaderProgram(shaderProg.p()); m_effWithAllUniforms->setUniform(new UniformFloat("u_color0", Color3f(Color3::BLACK))); m_effWithAllUniforms->setUniform(new UniformFloat("u_color1", Color3f(Color3::GREEN))); m_effWithAllUniforms->setUniform(new UniformFloat("u_colorMixFactor", 1.0f)); // Box part ref<Part> boxPart = new Part; { BoxGenerator gen; gen.setCenterAndExtent(Vec3d(-2, 0, 0), Vec3d(2, 2, 2)); GeometryBuilderDrawableGeo builder; gen.generate(&builder); boxPart->setDrawable(builder.drawableGeo().p()); } // Sphere part ref<Part> spherePart = new Part; { GeometryBuilderDrawableGeo builder; GeometryUtils::createSphere(1, 10, 10, &builder); spherePart->setDrawable(builder.drawableGeo().p()); } // Cylinder part ref<Part> cylinderPart = new Part; { GeometryBuilderDrawableGeo builder; GeometryUtils::createObliqueCylinder(1, 1, 2, 0, 0, 10, true, true, true, 1, &builder); ref<DrawableGeo> geo = builder.drawableGeo(); geo->transform(Mat4d::fromTranslation(Vec3d(2, 0, -1))); cylinderPart->setDrawable(geo.p()); } ref<ModelBasicList> myModel = new ModelBasicList; boxPart->setEffect(m_effNoUniforms.p()); spherePart->setEffect(m_effWithSomeUniforms.p()); cylinderPart->setEffect(m_effWithAllUniforms.p()); myModel->addPart(boxPart.p()); myModel->addPart(spherePart.p()); myModel->addPart(cylinderPart.p()); myModel->updateBoundingBoxesRecursive(); m_renderSequence->firstRendering()->scene()->addModel(myModel.p()); BoundingBox bb = myModel->boundingBox(); if (bb.isValid()) { m_camera->fitView(bb, Vec3d::Y_AXIS, Vec3d::Z_AXIS); } applyCurrentProperties(); return true; }
/*************************************************************** * Function: setSurfaceScalingHint() ***************************************************************/ void CAVEGroupIconSurface::setSurfaceScalingHint(const BoundingBox& boundingbox) { gScaleVal = (CAVEGeodeIcon::gSphereBoundRadius) / (boundingbox.radius()); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool PointSprites::onInitialize() { ref<ModelBasicList> model = new ModelBasicList; bool useShaders = true; { GeometryBuilderDrawableGeo builder; GeometryUtils::createSphere(1, 10, 10, &builder); ref<DrawableGeo> geo = builder.drawableGeo(); ref<Effect> eff = new Effect; if (useShaders) { cvf::ShaderProgramGenerator gen("SimpleHeadlight", cvf::ShaderSourceProvider::instance()); gen.configureStandardHeadlightColor(); ref<ShaderProgram> prog = gen.generate(); eff->setShaderProgram(prog.p()); eff->setUniform(new UniformFloat("u_color", Color4f(Color3::YELLOW))); } else { eff->setRenderState(new RenderStateMaterial_FF(RenderStateMaterial_FF::PURE_YELLOW)); } ref<Part> part = new Part; part->setDrawable(geo.p()); part->setEffect(eff.p()); model->addPart(part.p()); } { ref<Vec3fArray> vertices = new Vec3fArray; vertices->reserve(10); vertices->add(Vec3f(0, 0, 0)); vertices->add(Vec3f(-3, 0, 0)); vertices->add(Vec3f(3, 0, 0)); ref<UIntArray> indices = new UIntArray(vertices->size()); indices->setConsecutive(0); ref<PrimitiveSetIndexedUInt> primSet = new PrimitiveSetIndexedUInt(PT_POINTS); primSet->setIndices(indices.p()); ref<DrawableGeo> geo = new DrawableGeo; geo->setVertexArray(vertices.p()); geo->addPrimitiveSet(primSet.p()); ref<Effect> eff = new Effect; if (useShaders) { bool useTextureSprite = true; cvf::ShaderProgramGenerator gen("PointSprites", cvf::ShaderSourceProvider::instance()); gen.addVertexCode(ShaderSourceRepository::vs_DistanceScaledPoints); if (useTextureSprite) gen.addFragmentCode(ShaderSourceRepository::src_TextureFromPointCoord); else gen.addFragmentCode(ShaderSourceRepository::src_Color); gen.addFragmentCode(ShaderSourceRepository::fs_CenterLitSpherePoints); ref<cvf::ShaderProgram> prog = gen.generate(); eff->setShaderProgram(prog.p()); eff->setUniform(new UniformFloat("u_pointRadius", 1.0f)); if (useTextureSprite) { ref<Texture> tex = createTexture(); ref<Sampler> sampler = new Sampler; sampler->setMinFilter(Sampler::LINEAR); sampler->setMagFilter(Sampler::NEAREST); sampler->setWrapModeS(Sampler::REPEAT); sampler->setWrapModeT(Sampler::REPEAT); ref<RenderStateTextureBindings> texBind = new RenderStateTextureBindings(tex.p(), sampler.p(), "u_texture2D"); eff->setRenderState(texBind.p()); } else { eff->setUniform(new UniformFloat("u_color", Color4f(Color3::RED))); } ref<RenderStatePoint> point = new RenderStatePoint(RenderStatePoint::PROGRAM_SIZE); point->enablePointSprite(true); eff->setRenderState(point.p()); } else { eff->setRenderState(new RenderStateLighting_FF(false)); eff->setRenderState(new RenderStateMaterial_FF(RenderStateMaterial_FF::PURE_MAGENTA)); ref<RenderStatePoint> point = new RenderStatePoint(RenderStatePoint::FIXED_SIZE); point->enablePointSprite(true); point->setSize(600.0f); eff->setRenderState(point.p()); } ref<Part> part = new Part; part->setDrawable(geo.p()); part->setEffect(eff.p()); model->addPart(part.p()); } model->updateBoundingBoxesRecursive(); m_renderSequence->firstRendering()->scene()->addModel(model.p()); BoundingBox bb = model->boundingBox(); if (bb.isValid()) { m_camera->fitView(bb, -Vec3d::Z_AXIS, Vec3d::Y_AXIS); if (m_usePerspective) { m_camera->setProjectionAsPerspective(m_fovScale*40.0, m_nearPlane, m_camera->farPlane()); } else { m_camera->setProjectionAsOrtho(m_fovScale*bb.extent().length(), m_nearPlane, m_camera->farPlane()); } } return true; }
void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool exportMorphs) { File meshFileSource(context_); meshFileSource.Open(inputFileName); if (!meshFile_->Load(meshFileSource)) ErrorExit("Could not load input file " + inputFileName); XMLElement root = meshFile_->GetRoot("mesh"); XMLElement subMeshes = root.GetChild("submeshes"); XMLElement skeletonLink = root.GetChild("skeletonlink"); if (root.IsNull()) ErrorExit("Could not load input file " + inputFileName); String skeletonName = skeletonLink.GetAttribute("name"); if (!skeletonName.Empty()) LoadSkeleton(GetPath(inputFileName) + GetFileName(skeletonName) + ".skeleton.xml"); // Check whether there's benefit of avoiding 32bit indices by splitting each submesh into own buffer XMLElement subMesh = subMeshes.GetChild("submesh"); unsigned totalVertices = 0; unsigned maxSubMeshVertices = 0; while (subMesh) { materialNames_.Push(subMesh.GetAttribute("material")); XMLElement geometry = subMesh.GetChild("geometry"); if (geometry) { unsigned vertices = geometry.GetInt("vertexcount"); totalVertices += vertices; if (maxSubMeshVertices < vertices) maxSubMeshVertices = vertices; } ++numSubMeshes_; subMesh = subMesh.GetNext("submesh"); } XMLElement sharedGeometry = root.GetChild("sharedgeometry"); if (sharedGeometry) { unsigned vertices = sharedGeometry.GetInt("vertexcount"); totalVertices += vertices; if (maxSubMeshVertices < vertices) maxSubMeshVertices = vertices; } if (!sharedGeometry && (splitSubMeshes || (totalVertices > 65535 && maxSubMeshVertices <= 65535))) { useOneBuffer_ = false; vertexBuffers_.Resize(numSubMeshes_); indexBuffers_.Resize(numSubMeshes_); } else { vertexBuffers_.Resize(1); indexBuffers_.Resize(1); } subMesh = subMeshes.GetChild("submesh"); unsigned indexStart = 0; unsigned vertexStart = 0; unsigned subMeshIndex = 0; PODVector<unsigned> vertexStarts; vertexStarts.Resize(numSubMeshes_); while (subMesh) { XMLElement geometry = subMesh.GetChild("geometry"); XMLElement faces = subMesh.GetChild("faces"); // If no submesh vertexbuffer, process the shared geometry, but do it only once unsigned vertices = 0; if (!geometry) { vertexStart = 0; if (!subMeshIndex) geometry = root.GetChild("sharedgeometry"); } if (geometry) vertices = geometry.GetInt("vertexcount"); ModelSubGeometryLodLevel subGeometryLodLevel; ModelVertexBuffer* vBuf; ModelIndexBuffer* iBuf; if (useOneBuffer_) { vBuf = &vertexBuffers_[0]; if (vertices) vBuf->vertices_.Resize(vertexStart + vertices); iBuf = &indexBuffers_[0]; subGeometryLodLevel.vertexBuffer_ = 0; subGeometryLodLevel.indexBuffer_ = 0; } else { vertexStart = 0; indexStart = 0; vBuf = &vertexBuffers_[subMeshIndex]; vBuf->vertices_.Resize(vertices); iBuf = &indexBuffers_[subMeshIndex]; subGeometryLodLevel.vertexBuffer_ = subMeshIndex; subGeometryLodLevel.indexBuffer_ = subMeshIndex; } // Store the start vertex for later use vertexStarts[subMeshIndex] = vertexStart; // Ogre may have multiple buffers in one submesh. These will be merged into one XMLElement bufferDef; if (geometry) bufferDef = geometry.GetChild("vertexbuffer"); while (bufferDef) { if (bufferDef.HasAttribute("positions")) vBuf->elementMask_ |= MASK_POSITION; if (bufferDef.HasAttribute("normals")) vBuf->elementMask_ |= MASK_NORMAL; if (bufferDef.HasAttribute("texture_coords")) { vBuf->elementMask_ |= MASK_TEXCOORD1; if (bufferDef.GetInt("texture_coords") > 1) vBuf->elementMask_ |= MASK_TEXCOORD2; } unsigned vertexNum = vertexStart; if (vertices) { XMLElement vertex = bufferDef.GetChild("vertex"); while (vertex) { XMLElement position = vertex.GetChild("position"); if (position) { // Convert from right- to left-handed float x = position.GetFloat("x"); float y = position.GetFloat("y"); float z = position.GetFloat("z"); Vector3 vec(x, y, -z); vBuf->vertices_[vertexNum].position_ = vec; boundingBox_.Merge(vec); } XMLElement normal = vertex.GetChild("normal"); if (normal) { // Convert from right- to left-handed float x = normal.GetFloat("x"); float y = normal.GetFloat("y"); float z = normal.GetFloat("z"); Vector3 vec(x, y, -z); vBuf->vertices_[vertexNum].normal_ = vec; } XMLElement uv = vertex.GetChild("texcoord"); if (uv) { float x = uv.GetFloat("u"); float y = uv.GetFloat("v"); Vector2 vec(x, y); vBuf->vertices_[vertexNum].texCoord1_ = vec; if (vBuf->elementMask_ & MASK_TEXCOORD2) { uv = uv.GetNext("texcoord"); if (uv) { float x = uv.GetFloat("u"); float y = uv.GetFloat("v"); Vector2 vec(x, y); vBuf->vertices_[vertexNum].texCoord2_ = vec; } } } vertexNum++; vertex = vertex.GetNext("vertex"); } } bufferDef = bufferDef.GetNext("vertexbuffer"); } unsigned triangles = faces.GetInt("count"); unsigned indices = triangles * 3; XMLElement triangle = faces.GetChild("face"); while (triangle) { unsigned v1 = triangle.GetInt("v1"); unsigned v2 = triangle.GetInt("v2"); unsigned v3 = triangle.GetInt("v3"); iBuf->indices_.Push(v3 + vertexStart); iBuf->indices_.Push(v2 + vertexStart); iBuf->indices_.Push(v1 + vertexStart); triangle = triangle.GetNext("face"); } subGeometryLodLevel.indexStart_ = indexStart; subGeometryLodLevel.indexCount_ = indices; if (vertexStart + vertices > 65535) iBuf->indexSize_ = sizeof(unsigned); XMLElement boneAssignments = subMesh.GetChild("boneassignments"); if (bones_.Size()) { if (boneAssignments) { XMLElement boneAssignment = boneAssignments.GetChild("vertexboneassignment"); while (boneAssignment) { unsigned vertex = boneAssignment.GetInt("vertexindex") + vertexStart; unsigned bone = boneAssignment.GetInt("boneindex"); float weight = boneAssignment.GetFloat("weight"); BoneWeightAssignment assign; assign.boneIndex_ = bone; assign.weight_ = weight; // Source data might have 0 weights. Disregard these if (assign.weight_ > 0.0f) { subGeometryLodLevel.boneWeights_[vertex].Push(assign); // Require skinning weight to be sufficiently large before vertex contributes to bone hitbox if (assign.weight_ > 0.33f) { // Check distance of vertex from bone to get bone max. radius information Vector3 bonePos = bones_[bone].derivedPosition_; Vector3 vertexPos = vBuf->vertices_[vertex].position_; float distance = (bonePos - vertexPos).Length(); if (distance > bones_[bone].radius_) { bones_[bone].collisionMask_ |= 1; bones_[bone].radius_ = distance; } // Build the hitbox for the bone bones_[bone].boundingBox_.Merge(bones_[bone].inverseWorldTransform_ * (vertexPos)); bones_[bone].collisionMask_ |= 2; } } boneAssignment = boneAssignment.GetNext("vertexboneassignment"); } } if ((subGeometryLodLevel.boneWeights_.Size()) && bones_.Size()) { vBuf->elementMask_ |= MASK_BLENDWEIGHTS | MASK_BLENDINDICES; bool sorted = false; // If amount of bones is larger than supported by HW skinning, must remap per submesh if (bones_.Size() > MAX_SKIN_MATRICES) { HashMap<unsigned, unsigned> usedBoneMap; unsigned remapIndex = 0; for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i = subGeometryLodLevel.boneWeights_.Begin(); i != subGeometryLodLevel.boneWeights_.End(); ++i) { // Sort the bone assigns by weight Sort(i->second_.Begin(), i->second_.End(), CompareWeights); // Use only the first 4 weights for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j) { unsigned originalIndex = i->second_[j].boneIndex_; if (!usedBoneMap.Contains(originalIndex)) { usedBoneMap[originalIndex] = remapIndex; remapIndex++; } i->second_[j].boneIndex_ = usedBoneMap[originalIndex]; } } // If still too many bones in one subgeometry, error if (usedBoneMap.Size() > MAX_SKIN_MATRICES) ErrorExit("Too many bones in submesh " + String(subMeshIndex + 1)); // Write mapping of vertex buffer bone indices to original bone indices subGeometryLodLevel.boneMapping_.Resize(usedBoneMap.Size()); for (HashMap<unsigned, unsigned>::Iterator j = usedBoneMap.Begin(); j != usedBoneMap.End(); ++j) subGeometryLodLevel.boneMapping_[j->second_] = j->first_; sorted = true; } for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i = subGeometryLodLevel.boneWeights_.Begin(); i != subGeometryLodLevel.boneWeights_.End(); ++i) { // Sort the bone assigns by weight, if not sorted yet in bone remapping pass if (!sorted) Sort(i->second_.Begin(), i->second_.End(), CompareWeights); float totalWeight = 0.0f; float normalizationFactor = 0.0f; // Calculate normalization factor in case there are more than 4 blend weights, or they do not add up to 1 for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j) totalWeight += i->second_[j].weight_; if (totalWeight > 0.0f) normalizationFactor = 1.0f / totalWeight; for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j) { vBuf->vertices_[i->first_].blendIndices_[j] = i->second_[j].boneIndex_; vBuf->vertices_[i->first_].blendWeights_[j] = i->second_[j].weight_ * normalizationFactor; } // If there are less than 4 blend weights, fill rest with zero for (unsigned j = i->second_.Size(); j < 4; ++j) { vBuf->vertices_[i->first_].blendIndices_[j] = 0; vBuf->vertices_[i->first_].blendWeights_[j] = 0.0f; } vBuf->vertices_[i->first_].hasBlendWeights_ = true; } } } else if (boneAssignments) PrintLine("No skeleton loaded, skipping skinning information"); // Calculate center for the subgeometry Vector3 center = Vector3::ZERO; for (unsigned i = 0; i < iBuf->indices_.Size(); i += 3) { center += vBuf->vertices_[iBuf->indices_[i]].position_; center += vBuf->vertices_[iBuf->indices_[i + 1]].position_; center += vBuf->vertices_[iBuf->indices_[i + 2]].position_; } if (iBuf->indices_.Size()) center /= (float)iBuf->indices_.Size(); subGeometryCenters_.Push(center); indexStart += indices; vertexStart += vertices; OptimizeIndices(&subGeometryLodLevel, vBuf, iBuf); PrintLine("Processed submesh " + String(subMeshIndex + 1) + ": " + String(vertices) + " vertices " + String(triangles) + " triangles"); Vector<ModelSubGeometryLodLevel> thisSubGeometry; thisSubGeometry.Push(subGeometryLodLevel); subGeometries_.Push(thisSubGeometry); subMesh = subMesh.GetNext("submesh"); subMeshIndex++; } // Process LOD levels, if any XMLElement lods = root.GetChild("levelofdetail"); if (lods) { try { // For now, support only generated LODs, where the vertices are the same XMLElement lod = lods.GetChild("lodgenerated"); while (lod) { float distance = M_EPSILON; if (lod.HasAttribute("fromdepthsquared")) distance = sqrtf(lod.GetFloat("fromdepthsquared")); if (lod.HasAttribute("value")) distance = lod.GetFloat("value"); XMLElement lodSubMesh = lod.GetChild("lodfacelist"); while (lodSubMesh) { unsigned subMeshIndex = lodSubMesh.GetInt("submeshindex"); unsigned triangles = lodSubMesh.GetInt("numfaces"); ModelSubGeometryLodLevel newLodLevel; ModelSubGeometryLodLevel& originalLodLevel = subGeometries_[subMeshIndex][0]; // Copy all initial values newLodLevel = originalLodLevel; ModelVertexBuffer* vBuf; ModelIndexBuffer* iBuf; if (useOneBuffer_) { vBuf = &vertexBuffers_[0]; iBuf = &indexBuffers_[0]; } else { vBuf = &vertexBuffers_[subMeshIndex]; iBuf = &indexBuffers_[subMeshIndex]; } unsigned indexStart = iBuf->indices_.Size(); unsigned indexCount = triangles * 3; unsigned vertexStart = vertexStarts[subMeshIndex]; newLodLevel.distance_ = distance; newLodLevel.indexStart_ = indexStart; newLodLevel.indexCount_ = indexCount; // Append indices to the original index buffer XMLElement triangle = lodSubMesh.GetChild("face"); while (triangle) { unsigned v1 = triangle.GetInt("v1"); unsigned v2 = triangle.GetInt("v2"); unsigned v3 = triangle.GetInt("v3"); iBuf->indices_.Push(v3 + vertexStart); iBuf->indices_.Push(v2 + vertexStart); iBuf->indices_.Push(v1 + vertexStart); triangle = triangle.GetNext("face"); } OptimizeIndices(&newLodLevel, vBuf, iBuf); subGeometries_[subMeshIndex].Push(newLodLevel); PrintLine("Processed LOD level for submesh " + String(subMeshIndex + 1) + ": distance " + String(distance)); lodSubMesh = lodSubMesh.GetNext("lodfacelist"); } lod = lod.GetNext("lodgenerated"); } } catch (...) {} } // Process poses/morphs // First find out all pose definitions if (exportMorphs) { try { Vector<XMLElement> poses; XMLElement posesRoot = root.GetChild("poses"); if (posesRoot) { XMLElement pose = posesRoot.GetChild("pose"); while (pose) { poses.Push(pose); pose = pose.GetNext("pose"); } } // Then process animations using the poses XMLElement animsRoot = root.GetChild("animations"); if (animsRoot) { XMLElement anim = animsRoot.GetChild("animation"); while (anim) { String name = anim.GetAttribute("name"); float length = anim.GetFloat("length"); HashSet<unsigned> usedPoses; XMLElement tracks = anim.GetChild("tracks"); if (tracks) { XMLElement track = tracks.GetChild("track"); while (track) { XMLElement keyframes = track.GetChild("keyframes"); if (keyframes) { XMLElement keyframe = keyframes.GetChild("keyframe"); while (keyframe) { float time = keyframe.GetFloat("time"); XMLElement poseref = keyframe.GetChild("poseref"); // Get only the end pose if (poseref && time == length) usedPoses.Insert(poseref.GetInt("poseindex")); keyframe = keyframe.GetNext("keyframe"); } } track = track.GetNext("track"); } } if (usedPoses.Size()) { ModelMorph newMorph; newMorph.name_ = name; if (useOneBuffer_) newMorph.buffers_.Resize(1); else newMorph.buffers_.Resize(usedPoses.Size()); unsigned bufIndex = 0; for (HashSet<unsigned>::Iterator i = usedPoses.Begin(); i != usedPoses.End(); ++i) { XMLElement pose = poses[*i]; unsigned targetSubMesh = pose.GetInt("index"); XMLElement poseOffset = pose.GetChild("poseoffset"); if (useOneBuffer_) newMorph.buffers_[bufIndex].vertexBuffer_ = 0; else newMorph.buffers_[bufIndex].vertexBuffer_ = targetSubMesh; newMorph.buffers_[bufIndex].elementMask_ = MASK_POSITION; ModelVertexBuffer* vBuf = &vertexBuffers_[newMorph.buffers_[bufIndex].vertexBuffer_]; while (poseOffset) { // Convert from right- to left-handed unsigned vertexIndex = poseOffset.GetInt("index") + vertexStarts[targetSubMesh]; float x = poseOffset.GetFloat("x"); float y = poseOffset.GetFloat("y"); float z = poseOffset.GetFloat("z"); Vector3 vec(x, y, -z); if (vBuf->morphCount_ == 0) { vBuf->morphStart_ = vertexIndex; vBuf->morphCount_ = 1; } else { unsigned first = vBuf->morphStart_; unsigned last = first + vBuf->morphCount_ - 1; if (vertexIndex < first) first = vertexIndex; if (vertexIndex > last) last = vertexIndex; vBuf->morphStart_ = first; vBuf->morphCount_ = last - first + 1; } ModelVertex newVertex; newVertex.position_ = vec; newMorph.buffers_[bufIndex].vertices_.Push(MakePair(vertexIndex, newVertex)); poseOffset = poseOffset.GetNext("poseoffset"); } if (!useOneBuffer_) ++bufIndex; } morphs_.Push(newMorph); PrintLine("Processed morph " + name + " with " + String(usedPoses.Size()) + " sub-poses"); } anim = anim.GetNext("animation"); } } } catch (...) {} } // Check any of the buffers for vertices with missing blend weight assignments for (unsigned i = 0; i < vertexBuffers_.Size(); ++i) { if (vertexBuffers_[i].elementMask_ & MASK_BLENDWEIGHTS) { for (unsigned j = 0; j < vertexBuffers_[i].vertices_.Size(); ++j) if (!vertexBuffers_[i].vertices_[j].hasBlendWeights_) ErrorExit("Found a vertex with missing skinning information"); } } // Tangent generation if (generateTangents) { for (unsigned i = 0; i < subGeometries_.Size(); ++i) { for (unsigned j = 0; j < subGeometries_[i].Size(); ++j) { ModelVertexBuffer& vBuf = vertexBuffers_[subGeometries_[i][j].vertexBuffer_]; ModelIndexBuffer& iBuf = indexBuffers_[subGeometries_[i][j].indexBuffer_]; unsigned indexStart = subGeometries_[i][j].indexStart_; unsigned indexCount = subGeometries_[i][j].indexCount_; // If already has tangents, do not regenerate if (vBuf.elementMask_ & MASK_TANGENT || vBuf.vertices_.Empty() || iBuf.indices_.Empty()) continue; vBuf.elementMask_ |= MASK_TANGENT; if ((vBuf.elementMask_ & (MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1)) != (MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1)) ErrorExit("To generate tangents, positions normals and texcoords are required"); GenerateTangents(&vBuf.vertices_[0], sizeof(ModelVertex), &iBuf.indices_[0], sizeof(unsigned), indexStart, indexCount, offsetof(ModelVertex, normal_), offsetof(ModelVertex, texCoord1_), offsetof(ModelVertex, tangent_)); PrintLine("Generated tangents"); } } } }
const bool BoundingBox::intersects(const BoundingBox &box) const { return(this->minCorner() < box.maxCorner() && this->maxCorner() > box.minCorner()); }
/* ==================== build ==================== */ VOID Game::build() { GUARD(Game::build); // build the color texture Image* image = GNEW(Image); CHECK(image); image->Width(256); image->Height(256); image->Depth(1); image->PixelFormat(PF_RGBA); image->DataType(DT_UNSIGNED_BYTE); mColorTexPtr = GNEW(Texture); CHECK(mColorTexPtr); mColorTexPtr->Load(image); // build the color rt mColorRTPtr = GNEW(Target(mColorTexPtr.Ptr())); CHECK(mColorRTPtr); // build the primitive mQuadPtr = GNEW(Primitive); CHECK(mQuadPtr); mQuadPtr->SetType(Primitive::PT_TRIANGLES); // set the wvp Constant* wvp_constant_ptr = GNEW(Constant); CHECK(wvp_constant_ptr); wvp_constant_ptr->SetMatrix(Matrix()); mQuadPtr->SetConstant("gWVP",wvp_constant_ptr); // set the color texture Constant* texture_constant_ptr = GNEW(Constant); CHECK(texture_constant_ptr); texture_constant_ptr->SetTexture(mColorTexPtr.Ptr()); mQuadPtr->SetConstant("gBaseTex",texture_constant_ptr); // set the shader Str shader_key_name = "shader/default.xml"; KeyPtr shader_key_ptr = Key::Find(shader_key_name.c_str()); if(shader_key_ptr == NULL) { Shader*shader = GNEW(Shader); CHECK(shader); shader->Load(GLoad(shader_key_name.c_str())); shader_key_ptr = GNEW(Key(shader_key_name.c_str(), shader)); CHECK(shader_key_ptr); } mKeys.push_back(shader_key_ptr); mQuadPtr->SetShader(dynamic_cast<Shader*>(shader_key_ptr->Ptr()),"p0"); // build the vertex buffer F32 x = 0.0f, y = 0.0f, w = 256, h = 256; DVT vertexes[] = { {x, y, 0, 0, 0}, {x+w, y, 0, 1, 0}, {x+w, y+h, 0, 1, 1}, {x, y+h, 0, 0, 1}, }; VertexBufferPtr vb_ptr = GNEW(VertexBuffer); CHECK(vb_ptr); { GDataPtr vd_ptr = GNEW(GData); CHECK(vd_ptr); vd_ptr->Size(3*sizeof(U32) + 3*sizeof(U8) + sizeof(vertexes)); U8*data_ptr = (U8*)vd_ptr->Ptr(); *(U32*)data_ptr = MAKEFOURCC('G','V','B','O'); data_ptr += sizeof(U32); *(U32*)data_ptr = sizeof(vertexes)/sizeof(DVT); data_ptr += sizeof(U32); *(U32*)data_ptr = sizeof(DVT); data_ptr += sizeof(U32); *(U8*)data_ptr = 2; data_ptr += sizeof(U8); *(U8*)data_ptr = VertexBuffer::VT_3F; data_ptr += sizeof(U8); *(U8*)data_ptr = VertexBuffer::VT_2F; data_ptr += sizeof(U8); ::memcpy(data_ptr, vertexes, sizeof(vertexes)); data_ptr += sizeof(vertexes); vb_ptr->Load(vd_ptr.Ptr()); } mQuadPtr->SetVertexBuffer(vb_ptr.Ptr()); // build the index const U16 indexes[] = { 3, 0, 2, 2, 0, 1 }; IndexBufferPtr ib_ptr = GNEW(IndexBuffer); CHECK(ib_ptr); { GDataPtr id_ptr = GNEW(GData); CHECK(id_ptr); id_ptr->Size(3*sizeof(U32) + sizeof(indexes)); U8*data_ptr = (U8*)id_ptr->Ptr(); *(U32*)data_ptr = MAKEFOURCC('G','I','B','O'); data_ptr += sizeof(U32); *(U32*)data_ptr = sizeof(indexes)/sizeof(U16); data_ptr += sizeof(U32); *(U32*)data_ptr = sizeof(U16); data_ptr += sizeof(U32); ::memcpy(data_ptr, &indexes[0], sizeof(indexes)); data_ptr += sizeof(indexes); ib_ptr->Load(id_ptr.Ptr()); } mQuadPtr->SetIndexBuffer(ib_ptr.Ptr()); // build the bounding box BoundingBox box; box.set(MAX_F32,MAX_F32,MAX_F32,MIN_F32,MIN_F32,MIN_F32); for(U32 i = 0; i < sizeof(vertexes)/sizeof(DVTN); i++)box.expand(vertexes[i].point); mQuadPtr->SetBox(box); UNGUARD; }
const bool BoundingBox::contains(const BoundingBox &box) const { return(box.minCorner() >= this->minCorner() && box.maxCorner() <= this->maxCorner()); }
bool BridgeDetector::detect_angle() { if (this->_edges.empty() || this->_anchors.empty()) return false; /* Outset the bridge expolygon by half the amount we used for detecting anchors; we'll use this one to clip our test lines and be sure that their endpoints are inside the anchors and not on their contours leading to false negatives. */ Polygons clip_area; offset(this->expolygon, &clip_area, +this->extrusion_width/2); /* we'll now try several directions using a rudimentary visibility check: bridge in several directions and then sum the length of lines having both endpoints within anchors */ // we test angles according to configured resolution std::vector<double> angles; for (int i = 0; i <= PI/this->resolution; ++i) angles.push_back(i * this->resolution); // we also test angles of each bridge contour { Polygons pp = this->expolygon; for (Polygons::const_iterator p = pp.begin(); p != pp.end(); ++p) { Lines lines = p->lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) angles.push_back(line->direction()); } } /* we also test angles of each open supporting edge (this finds the optimal angle for C-shaped supports) */ for (Polylines::const_iterator edge = this->_edges.begin(); edge != this->_edges.end(); ++edge) { if (edge->first_point().coincides_with(edge->last_point())) continue; angles.push_back(Line(edge->first_point(), edge->last_point()).direction()); } // remove duplicates double min_resolution = PI/180.0; // 1 degree std::sort(angles.begin(), angles.end()); for (size_t i = 1; i < angles.size(); ++i) { if (Slic3r::Geometry::directions_parallel(angles[i], angles[i-1], min_resolution)) { angles.erase(angles.begin() + i); --i; } } /* compare first value with last one and remove the greatest one (PI) in case they are parallel (PI, 0) */ if (Slic3r::Geometry::directions_parallel(angles.front(), angles.back(), min_resolution)) angles.pop_back(); BridgeDirectionComparator bdcomp(this->extrusion_width); double line_increment = this->extrusion_width; bool have_coverage = false; for (std::vector<double>::const_iterator angle = angles.begin(); angle != angles.end(); ++angle) { Polygons my_clip_area = clip_area; ExPolygons my_anchors = this->_anchors; // rotate everything - the center point doesn't matter for (Polygons::iterator it = my_clip_area.begin(); it != my_clip_area.end(); ++it) it->rotate(-*angle, Point(0,0)); for (ExPolygons::iterator it = my_anchors.begin(); it != my_anchors.end(); ++it) it->rotate(-*angle, Point(0,0)); // generate lines in this direction BoundingBox bb; for (ExPolygons::const_iterator it = my_anchors.begin(); it != my_anchors.end(); ++it) bb.merge((Points)*it); Lines lines; for (coord_t y = bb.min.y; y <= bb.max.y; y += line_increment) lines.push_back(Line(Point(bb.min.x, y), Point(bb.max.x, y))); Lines clipped_lines; intersection(lines, my_clip_area, &clipped_lines); // remove any line not having both endpoints within anchors for (size_t i = 0; i < clipped_lines.size(); ++i) { Line &line = clipped_lines[i]; if (!Slic3r::Geometry::contains(my_anchors, line.a) || !Slic3r::Geometry::contains(my_anchors, line.b)) { clipped_lines.erase(clipped_lines.begin() + i); --i; } } std::vector<double> lengths; double total_length = 0; for (Lines::const_iterator line = clipped_lines.begin(); line != clipped_lines.end(); ++line) { double len = line->length(); lengths.push_back(len); total_length += len; } if (total_length) have_coverage = true; // sum length of bridged lines bdcomp.dir_coverage[*angle] = total_length; /* The following produces more correct results in some cases and more broken in others. TODO: investigate, as it looks more reliable than line clipping. */ // $directions_coverage{$angle} = sum(map $_->area, @{$self->coverage($angle)}) // 0; // max length of bridged lines bdcomp.dir_avg_length[*angle] = !lengths.empty() ? *std::max_element(lengths.begin(), lengths.end()) : 0; } // if no direction produced coverage, then there's no bridge direction if (!have_coverage) return false; // sort directions by score std::sort(angles.begin(), angles.end(), bdcomp); this->angle = angles.front(); if (this->angle >= PI) this->angle -= PI; #ifdef SLIC3R_DEBUG printf(" Optimal infill angle is %d degrees\n", (int)Slic3r::Geometry::rad2deg(this->angle)); #endif return true; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(BoxGeneratorTest, GenerateSimple) { // From min/max { BoxGenerator gen; gen.setMinMax(Vec3d(10, 20, 30), Vec3d(20, 40, 60)); BuilderTrisQuads builder; gen.generate(&builder); BoundingBox bb = builder.vertexBoundingBox(); EXPECT_DOUBLE_EQ(10, bb.min().x()); EXPECT_DOUBLE_EQ(20, bb.min().y()); EXPECT_DOUBLE_EQ(30, bb.min().z()); EXPECT_DOUBLE_EQ(20, bb.max().x()); EXPECT_DOUBLE_EQ(40, bb.max().y()); EXPECT_DOUBLE_EQ(60, bb.max().z()); EXPECT_EQ(0, builder.triCount()); EXPECT_EQ(6, builder.quadCount()); } // From origin and extent { BoxGenerator gen; gen.setOriginAndExtent(Vec3d(10, 20, 30), Vec3d(100, 200, 300)); BuilderTrisQuads builder; gen.generate(&builder); BoundingBox bb = builder.vertexBoundingBox(); EXPECT_DOUBLE_EQ(10, bb.min().x()); EXPECT_DOUBLE_EQ(20, bb.min().y()); EXPECT_DOUBLE_EQ(30, bb.min().z()); EXPECT_DOUBLE_EQ(110, bb.max().x()); EXPECT_DOUBLE_EQ(220, bb.max().y()); EXPECT_DOUBLE_EQ(330, bb.max().z()); } // From center and extent { BoxGenerator gen; gen.setCenterAndExtent(Vec3d(100, 200, 300), Vec3d(10, 20, 30)); BuilderTrisQuads builder; gen.generate(&builder); BoundingBox bb = builder.vertexBoundingBox(); EXPECT_DOUBLE_EQ(95, bb.min().x()); EXPECT_DOUBLE_EQ(190, bb.min().y()); EXPECT_DOUBLE_EQ(285, bb.min().z()); EXPECT_DOUBLE_EQ(105, bb.max().x()); EXPECT_DOUBLE_EQ(210, bb.max().y()); EXPECT_DOUBLE_EQ(315, bb.max().z()); } }
void process_goturn_detection(Mat *img, double time_stamp) { char string1[128]; CvFont font; bool recovery = false; static int cont = 0; static int first = 0; int step = 10; //cv::Mat mat_image=cvarrToMat(&img); static Mat prev_image; prev_image = img->clone(); if(box.x1_ != -1.0) { tracker.Track(*img, ®ressor, &box); if (cont > 30) { calculate_box_average(box, last_track, img, step, cont); // recovery = true; } //Apenas para publicar-ainda falta definir average_box_confidence = 1.0; last_track[(cont%30)].prev_image = prev_image; last_track[(cont%30)].prev_box = box; box.DrawBoundingBox(img); cont++; tracker.Init(*img, box, ®ressor); } cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, .4, .5, 0, 1, 8); // cvRectangle(&prev_image, cvPoint(0, 0), cvPoint(img.width, 50), CV_RGB(0, 0, 255), CV_FILLED, 8, 0); // cvPutText(&prev_image.data, string1, cvPoint(25, 25), &font, CV_RGB(255, 255, 255)); // draw the box sprintf(string1, "Time:%.2f, FPS:%d", time_stamp, disp_last_fps); cv::Size s = img->size(); cv::Point textOrg(25,25); cv::rectangle(*img, cv::Point(0, 0), cv::Point(s.width, 50), Scalar::all(0), -1); cv::putText(*img, string1,textOrg,FONT_HERSHEY_SIMPLEX, 0.4,Scalar::all(255),1,8); cv::imshow(window_name, *img); char c = cv::waitKey(2); switch (c) { case 'r': CvRect rect; if (getBBFromUser(img, rect, window_name) == 0) { return; } box.x1_ = rect.x; box.y1_ = rect.y; box.x2_ = rect.x+rect.width; box.y2_ = rect.y+rect.height; last_track[(cont%30)].prev_image = prev_image; last_track[(cont%30)].prev_box = box; cont++; tracker.Init(*img, box, ®ressor); // first = 1; // tracker.Track(*img, ®ressor, &box); break; case 'q': exit(0); } // Track and estimate the bounding box location. }
bool DynamicNavigationMesh::Build(const BoundingBox& boundingBox) { URHO3D_PROFILE(BuildPartialNavigationMesh); if (!node_) return false; if (!navMesh_) { URHO3D_LOGERROR("Navigation mesh must first be built fully before it can be partially rebuilt"); return false; } if (!node_->GetWorldScale().Equals(Vector3::ONE)) URHO3D_LOGWARNING("Navigation mesh root node has scaling. Agent parameters may not work as intended"); BoundingBox localSpaceBox = boundingBox.Transformed(node_->GetWorldTransform().Inverse()); float tileEdgeLength = (float)tileSize_ * cellSize_; Vector<NavigationGeometryInfo> geometryList; CollectGeometries(geometryList); int sx = Clamp((int)((localSpaceBox.min_.x_ - boundingBox_.min_.x_) / tileEdgeLength), 0, numTilesX_ - 1); int sz = Clamp((int)((localSpaceBox.min_.z_ - boundingBox_.min_.z_) / tileEdgeLength), 0, numTilesZ_ - 1); int ex = Clamp((int)((localSpaceBox.max_.x_ - boundingBox_.min_.x_) / tileEdgeLength), 0, numTilesX_ - 1); int ez = Clamp((int)((localSpaceBox.max_.z_ - boundingBox_.min_.z_) / tileEdgeLength), 0, numTilesZ_ - 1); unsigned numTiles = 0; for (int z = sz; z <= ez; ++z) { for (int x = sx; x <= ex; ++x) { dtCompressedTileRef existing[TILECACHE_MAXLAYERS]; const int existingCt = tileCache_->getTilesAt(x, z, existing, maxLayers_); for (int i = 0; i < existingCt; ++i) { unsigned char* data = 0x0; if (!dtStatusFailed(tileCache_->removeTile(existing[i], &data, 0)) && data != 0x0) dtFree(data); } TileCacheData tiles[TILECACHE_MAXLAYERS]; int layerCt = BuildTile(geometryList, x, z, tiles); for (int i = 0; i < layerCt; ++i) { dtCompressedTileRef tileRef; int status = tileCache_->addTile(tiles[i].data, tiles[i].dataSize, DT_COMPRESSEDTILE_FREE_DATA, &tileRef); if (dtStatusFailed((dtStatus)status)) { dtFree(tiles[i].data); tiles[i].data = 0x0; } else { tileCache_->buildNavMeshTile(tileRef, navMesh_); ++numTiles; } } } } URHO3D_LOGDEBUG("Rebuilt " + String(numTiles) + " tiles of the navigation mesh"); return true; }
const Vector3F Geometry::boundingCenter() const { BoundingBox box = calculateBBox(); return box.center(); }
/*! * \brief Static function for box intersection. Return false if they do not * intersect. * * \param box_A Bounding box A. * * \param box_B Bounding box B. * * \param intersection A bounding box that is equivalent to the inersection of * box A and box B. Box A and B can be provided in any order (the * intersection of box A with box B is equal to the intersection of box B with * box A). * * \return Return true if the boxes intersect. False if they do not. */ bool BoundingBox::intersectBoxes( const BoundingBox& box_A, const BoundingBox& box_B, BoundingBox& intersection) { Teuchos::Tuple<double,6> bounds_A = box_A.getBounds(); Teuchos::Tuple<double,6> bounds_B = box_B.getBounds(); double x_min, y_min, z_min, x_max, y_max, z_max; // Test for no overlap in X. if ( bounds_A[0] > bounds_B[3] || bounds_A[3] < bounds_B[0] ) { return false; } // Test for no overlap in Y. if ( bounds_A[1] > bounds_B[4] || bounds_A[4] < bounds_B[1] ) { return false; } // Test for no overlap in Z. if ( bounds_A[2] > bounds_B[5] || bounds_A[5] < bounds_B[2] ) { return false; } // Get overlap in X. if ( bounds_A[0] > bounds_B[0] ) { x_min = bounds_A[0]; } else { x_min = bounds_B[0]; } if ( bounds_A[3] > bounds_B[3] ) { x_max = bounds_B[3]; } else { x_max = bounds_A[3]; } // Get overlap in Y. if ( bounds_A[1] > bounds_B[1] ) { y_min = bounds_A[1]; } else { y_min = bounds_B[1]; } if ( bounds_A[4] > bounds_B[4] ) { y_max = bounds_B[4]; } else { y_max = bounds_A[4]; } // Get overlap in Z. if ( bounds_A[2] > bounds_B[2] ) { z_min = bounds_A[2]; } else { z_min = bounds_B[2]; } if ( bounds_A[5] > bounds_B[5] ) { z_max = bounds_B[5]; } else { z_max = bounds_A[5]; } intersection = BoundingBox( x_min, y_min, z_min, x_max, y_max, z_max ); return true; }
/** This routine creates the text for the slider value and sets the correct position relative to the position indicator. @param xPos position of slider value string */ ref_ptr<Geode> OSGVruiSlider::createText(float xPos) { if (!numberText) { textNode = new Geode(); numberText = new Text(); numberText->setDataVariance(Object::DYNAMIC); numberText->setFont(OSGVruiPresets::getFontFile()); numberText->setDrawMode(Text::TEXT); numberText->setColor(Vec4(1.0f, 1.0f, 1.0f, 1.0f)); numberText->setAlignment(Text::CENTER_BASE_LINE); numberText->setLayout(Text::LEFT_TO_RIGHT); numberText->setAxisAlignment(Text::XY_PLANE); sliderDialSize = slider->getDialSize(); numberText->setCharacterSize(sliderDialSize * 2.0f); textNode->setStateSet(OSGVruiPresets::getStateSetCulled(coUIElement::YELLOW)); textNode->addDrawable(numberText.get()); } if (sliderDialSize != slider->getDialSize()) { sliderDialSize = slider->getDialSize(); numberText->setCharacterSize(sliderDialSize * 2.0f); } char number[200]; float value = slider->getValue(); int precision = slider->getPrecision(); if (slider->isInteger()) { sprintf(number, "%d", (int)value); } else { sprintf(number, "%.*f", precision, value); } numberText->setText(number, String::ENCODING_UTF8); numberText->dirtyBound(); #if OSG_VERSION_GREATER_OR_EQUAL(3, 3, 2) BoundingBox stringBoundingBox = numberText->getBoundingBox(); #else BoundingBox stringBoundingBox = numberText->getBound(); #endif Vec3 position; float myWidth = slider->getWidth(); float dialSize = slider->getDialSize(); float xSize = stringBoundingBox.xMax() - stringBoundingBox.xMin(); if (xPos - xSize + dialSize < 0.0f) { position = Vec3(xSize - xPos - dialSize, 2.0f * dialSize, 0.0f); } else if (xPos + xSize - dialSize > myWidth) { position = Vec3(myWidth - xPos - xSize + dialSize, 2.0f * dialSize, 0.0f); } else { position = Vec3(0.0f, 2.0f * dialSize, 0.0f); } numberText->setPosition(position); return textNode; }
void LabelsRenderer::renderGraphNodesLabels(Graph *graph, const Camera &camera, const Color &selectionColor) { initFont(); BooleanProperty *viewSelection = graph->getProperty<BooleanProperty>("viewSelection"); ColorProperty *viewLabelColor = graph->getProperty<ColorProperty>("viewLabelColor"); StringProperty *viewLabel = graph->getProperty<StringProperty>("viewLabel"); Vec4i viewport = camera.getViewport(); vector<vector<Vec2f> > renderedLabelsScrRect; vector<BoundingBox> renderedLabelsScrBB; NVGcontext* vg = NanoVGManager::instance()->getNanoVGContext(); nvgBeginFrame(vg, camera.getViewport()[0], camera.getViewport()[1], camera.getViewport()[2], camera.getViewport()[3], 1.0); for (vector<node>::iterator it = _labelsToRender[graph].begin() ; it != _labelsToRender[graph].end() ; ++it) { if (_nodeLabelAspectRatio[graph].find(*it) == _nodeLabelAspectRatio[graph].end()) { continue; } BoundingBox nodeBB = labelBoundingBoxForNode(graph, *it); BoundingBox textBB = getLabelRenderingBoxScaled(nodeBB, _nodeLabelAspectRatio[graph][*it]); if (!_labelsScaled) { adjustTextBoundingBox(textBB, camera, _minSize, _maxSize, _nodeLabelNbLines[graph][*it]); } bool canRender = true; if (_occlusionTest) { if (!camera.hasRotation()) { BoundingBox textScrBB; textScrBB.expand(Vec3f(computeScreenPos(camera.transformMatrixBillboard(), viewport, textBB[0]), 0)); textScrBB.expand(Vec3f(computeScreenPos(camera.transformMatrixBillboard(), viewport, textBB[1]), 0)); for (size_t i = 0 ; i < renderedLabelsScrBB.size() ; ++i) { if (textScrBB.intersect(renderedLabelsScrBB[i])) { canRender = false; break; } } if (canRender) { renderedLabelsScrBB.push_back(textScrBB); } } else { vector<Vec2f> textScrRect; textScrRect.push_back(computeScreenPos(camera.transformMatrix(), viewport, textBB[0])); textScrRect.push_back(computeScreenPos(camera.transformMatrix(), viewport, Vec3f(textBB[0][0]+textBB.width(), textBB[0][1], textBB[0][2]))); textScrRect.push_back(computeScreenPos(camera.transformMatrix(), viewport, textBB[1])); textScrRect.push_back(computeScreenPos(camera.transformMatrix(), viewport, Vec3f(textBB[0][0], textBB[0][1]+textBB.height(), textBB[0][2]))); for (size_t i = 0 ; i < renderedLabelsScrRect.size() ; ++i) { if (convexPolygonsIntersect(textScrRect, renderedLabelsScrRect[i])) { canRender = false; break; } } if (canRender) { renderedLabelsScrRect.push_back(textScrRect); } } } if (canRender) { Vec2f textBBMinScr = computeScreenPos(camera.transformMatrix(), viewport, textBB[0]); Vec2f textBBMaxScr = computeScreenPos(camera.transformMatrix(), viewport, textBB[1]); BoundingBox bb; bb.expand(Vec3f(textBBMinScr[0], viewport[3] - textBBMinScr[1])); bb.expand(Vec3f(textBBMaxScr[0], viewport[3] - textBBMaxScr[1])); renderText(vg, viewLabel->getNodeValue(*it), bb, viewSelection->getNodeValue(*it) ? selectionColor : viewLabelColor->getNodeValue(*it)); } } nvgEndFrame(vg); }
void ImagePane::paintEvent(QPaintEvent* /*event*/) { QPainter painter(this); //draw the transformed version of the text-object image painter.drawImage(0, 0, transformedImage); //then we draw the bounding boxes //TODO inscriptions with at least one graph are a different color (?) //in case index numbers are visible, set font QFont font; font.setPixelSize(30/zoom); //TODO make font size dependent on resolution painter.setFont(font); QPen pen; pen.setWidth(0); pen.setColor(Qt::red); painter.setPen(pen); //make a list of bounding boxes according to current mode BoxList currentBoxList; //this is a list of all boxes currentBoxList.clear(); switch(mode) { case SURFACE: currentBoxList.append(*surf); //list of one item, consting of the surface bounding box break; case INSCRIPTION: for(int i=0; i < surf->inscriptionCount(); i++) currentBoxList.insertBox(surf->inscrAt(i), i); break; case GRAPH: for(int i=0; i < surf->ptrInscrAt(currentInscrIndex)->count(); i++) currentBoxList.insertBox(surf->ptrInscrAt(currentInscrIndex)->at(i), i); break; default: break; } //iterate through the list of bounding boxes for (int i=0; i<currentBoxList.size(); i++) { BoundingBox currentBox = currentBoxList.at(i); //the bounding boxes need to be rotated and scaled QTransform boxTransform; //identity matrix //first we need to handle the bounding box's own rotation //by inverting the true matrix that was applied to the image //at the time each bounding box was created //(note: we don't need to worry about scale, as we took account of that //when the bounding box was created) boxTransform.rotate(currentBox.getRotation()); boxTransform = QImage::trueMatrix(boxTransform, currentImage.width(), currentImage.height()); boxTransform = boxTransform.inverted(); //then we compound the above matrix with the current transformation of the image QTransform imageTrueTransform = QImage::trueMatrix(transform, currentImage.width(), currentImage.height()); painter.setWorldTransform(boxTransform * imageTrueTransform); //now draw the box //pen color is red; set the pen-color to green if this is the current box. if(i==currentBoxIndex) { QPen pen; pen.setWidth(0); pen.setColor(Qt::green); painter.setPen(pen); } painter.drawRect(currentBox); //and add an (optional) index number if(indexNumbersVisible) { painter.drawText(currentBox.left(), currentBox.top(), 50/zoom, 50/zoom, Qt::AlignBottom, QString("%1").arg(i+1)); //visible index, so base = 1, not zero } //return pen color to red (might be green) QPen pen; pen.setWidth(0); pen.setColor(Qt::red); painter.setPen(Qt::red); } //if label is not resized, it will stay large on zoom out //resulting in misleading / redundant scroll bars resize(transformedImage.size()); // keep label same size as image }
//=========================================================================== void CellDivision::constructCells() //=========================================================================== { // @@@ NOTE // // This implementation depends upon using bounding boxes that are // aligned with the principal axis and box-shaped. // First we check if big_box_ is valid. @jbt if (!big_box_.valid()) { MESSAGE("Big box is invalid - returning empty cell vector."); cells_.clear(); return; } if (dim_ < 1) { MESSAGE("Incorrect number of space dimensions."); cells_.clear(); return; } // We partition space into cells. makeCoords(); double tol = 1.0e-9; // VSK, 082017. To avoid loosing surfaces in // planar cases int ncells = ncells_[0]; for (int i = 1; i < dim_; ++i) ncells *= ncells_[i]; cells_.resize(ncells); Point low = big_box_.low(); Point len = big_box_.high() - low; cell_delta_.resize(dim_); for (int i = 0; i < dim_; ++i) cell_delta_[i] = len[i] / ncells_[i]; Point corner; corner.resize(dim_); for (int i = 0; i < ncells; ++i) { for (int dd = 0; dd < dim_; ++dd) { corner[dd] = low[dd] + coords_[i][dd] * cell_delta_[dd]; } cells_[i].setBox(BoundingBox(corner, corner + cell_delta_)); } // Now that we have the cells, we check every face, and add its pointer // to every cell overlapping its bounding box. for (size_t f=0; f<faces_.size(); ++f) { BoundingBox b = faces_[f]->boundingBox(); for (int i = 0; i < ncells; ++i) { if (b.overlaps(cells_[i].box(), tol)) { cells_[i].addFace(faces_[f]); cells_[i].addFaceBox(b); } } } // // The following code depends on dimensionality 3 - commenting out. @jbt // int i, j, k; // // // We partition space into cells. // cells_.resize(ncellsx_*ncellsy_*ncellsz_); // Point low = big_box_.low(); // Point len = big_box_.high() - low; // cell_delta_ = Point(len[0]/ncellsx_, len[1]/ncellsy_, len[2]/ncellsz_); // const Point& delta = cell_delta_; // // double x = low[0]; // double y = low[1]; // double z = low[2]; // Point corner; // // for (i=0; i<ncellsx_; ++i) { // y = low[1]; // for (j=0; j<ncellsy_; ++j) { // z = low[2]; // for (k=0; k<ncellsz_; ++k) { // corner.setValue(x, y, z); // cells_[i + j*ncellsx_ + k*ncellsx_*ncellsy_] // .setBox(BoundingBox(corner, corner + delta)); // z += delta[2]; // } // y += delta[1]; // } // x += delta[0]; // } // // int x1, x2, y1, y2, z1, z2; // Point lo, hi; // // Now that we have the cells, we check every face, and add its pointer // // to every cell overlapping its bounding box. // for (size_t f=0; f<faces_.size(); ++f) { // BoundingBox b = faces_[f]->boundingBox(); // lo = b.low(); // hi = b.high(); // cellContaining(lo, x1, y1, z1); // cellContaining(hi, x2, y2, z2); // for (i=x1; i<=x2; ++i) // for (j=y1; j<=y2; ++j) // for (k=z1; k<=z2; ++k) // { // cells_[i + j*ncellsx_ + k*ncellsx_*ncellsy_].addFace(faces_[f]); // cells_[i + j*ncellsx_ + k*ncellsx_*ncellsy_].addFaceBox(b); // } // } // //#ifdef DEBUG_CELLS // for (i=0; i<ncellsx_*ncellsy_*ncellsz_; ++i) { // cout << "Cell " << i << " has " // << cells_[i].num_faces() << " faces "; // for (j=0; j<cells_[i].num_faces(); ++j) // cout << cells_[i].face(j)->GetId() << " "; // cout << endl; // } //#endif }
void isab::Faker::decodedMapRequest(int len, const uint8* data, uint32 dst, int /*latOffset*/, int /*lonOffset*/, int /*hdgOffset*/, int /*spdOffset*/) { // decode data Buffer req(len); req.writeNextByteArray(data, len); BoundingBox* bb = BoundingBox::deserialize(&req); uint16 width = req.readNextUnaligned16bit(); uint16 height = req.readNextUnaligned16bit(); uint16 vbw = req.readNextUnaligned16bit(); uint16 vbh = req.readNextUnaligned16bit(); vbh = vbh; vbw = vbw; DBG("decodedMapRequest: width: %d, height: %d", width, height); //select map file #ifdef __SYMBIAN32__ const char* path = getGlobalData().m_writable_files_path; #else const char* path = LINUX_BASE_PATH; #endif #define SCNCRD(fmtspec) "(%"fmtspec",%"fmtspec")" const char* scfmt = SCNCRD(SCNd32)SCNCRD(SCNd32)SCNCRD("d")SCNCRD(SCNd32); int32 tlat = 0, tlon = 0, blat = 0, blon = 0, rww = 0, rwh = 0; int w = 0, h = 0; char filename[256] = {0}; const char* type = NULL; switch(bb->getBoxType()){ case BoundingBox::invalidBox: //error break; case BoundingBox::diameterBox: //zoom to turn, position, ... { DBG("DiameterBox request"); DiameterBox* db = static_cast<DiameterBox*>(bb); const char * const types[] = {"orig", "dest"}; char tmp[256] = {0}; for(size_t a = 0; (!type) && (a < sizeof(types)/sizeof(*types)); ++a){ snprintf(tmp, sizeof(tmp) - 1, "%s%dx%d%sdata.txt", path, width, height, types[a]); DBG("Testing file '%s' for coords (%"PRId32",%"PRId32")", tmp, db->getLat(), db->getLon()); FILE* dataf = fopen(tmp, "r"); if(dataf){ DBG("'%s' opened OK", tmp); tlat = tlon = blat = blon = rww = rwh = w = h = 0; if(8 == fscanf(dataf, scfmt, &tlat, &tlon, &blat, &blon, &rww, &rwh, &w, &h)){ DBG("(%"PRId32",%"PRId32")(%"PRId32",%"PRId32")" "(%"PRId32",%"PRId32")(%d,%d)", tlat, tlon, blat, blon, rww, rwh, w, h); if(BoxBox(tlat, tlon, blat, blon).Contains(db->getLat(), db->getLon())){ DBG("Contains(%"PRId32",%"PRId32")", db->getLat(), db->getLon()); type = types[a]; } } fclose(dataf); } } if(type == NULL){ type = "route"; } } break; case BoundingBox::boxBox: //zoom? case BoundingBox::vectorBox: //tracking case BoundingBox::routeBox: //zoom to route type = "route"; } if(type != NULL){ snprintf(filename, sizeof(filename) - 1, "%s%dx%d%s.gif", path, width, height, type); DBG("opening file %s", filename); FILE* mapfile = fopen(filename, "rb"); if(mapfile){ snprintf(filename, sizeof(filename) - 1, "%s%dx%d%sdata.txt", path, width, height, type); FILE* datafile = fopen(filename, "r"); if(datafile && (8 == fscanf(datafile, scfmt, &tlat, &tlon, &blat, &blon, &rww, &rwh, &w, &h))){ Buffer reply(5*1024); reply.writeNextUnaligned32bit(tlat); reply.writeNextUnaligned32bit(tlon); reply.writeNextUnaligned32bit(blat); reply.writeNextUnaligned32bit(blon); reply.writeNextUnaligned16bit(w); reply.writeNextUnaligned16bit(h); reply.writeNextUnaligned32bit(rww); reply.writeNextUnaligned32bit(rwh); int lengthpos = reply.getWritePos(); reply.writeNextUnaligned32bit(0); //buffer size reply.writeNextUnaligned16bit(GIF); int start = reply.getWritePos(); //buffer start const size_t BUFFER_LEN = 1024; uint8* buffer = new uint8[BUFFER_LEN]; size_t len = 0; while(BUFFER_LEN == (len = fread(buffer, sizeof(*buffer), BUFFER_LEN, mapfile))){ reply.writeNextByteArray(buffer, len); } reply.writeNextByteArray(buffer, len); delete[] buffer; int end = reply.setWritePos(lengthpos); reply.writeNextUnaligned32bit(end - start); m_interface-> NavServerComConsumerPublicRef().mapReply(reply.getLength(), reply.accessRawData(0), dst); fclose(datafile); } else { //data error m_interface->sendError(Nav2Error::NSC_OPERATION_NOT_SUPPORTED,dst); } fclose(mapfile); } else { m_interface->sendError(Nav2Error::NSC_OPERATION_NOT_SUPPORTED, dst); } } else { m_interface->sendError(Nav2Error::NSC_OPERATION_NOT_SUPPORTED, dst); } delete bb; }
double Area(const BoundingBox& bb){ return (bb.y2() - bb.y1())*(bb.x2() - bb.x1()); }
void NavigationMesh::GetTileGeometry(NavigationBuildData& build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box) { Matrix3x4 inverse = node_->GetWorldTransform().Inverse(); for (unsigned i = 0; i < geometryList.Size(); ++i) { if (box.IsInsideFast(geometryList[i].boundingBox_) != OUTSIDE) { const Matrix3x4& transform = geometryList[i].transform_; if (geometryList[i].component_->GetType() == OffMeshConnection::GetTypeStatic()) { OffMeshConnection* connection = static_cast<OffMeshConnection*>(geometryList[i].component_); Vector3 start = inverse * connection->GetNode()->GetWorldPosition(); Vector3 end = inverse * connection->GetEndPoint()->GetWorldPosition(); build.offMeshVertices_.Push(start); build.offMeshVertices_.Push(end); build.offMeshRadii_.Push(connection->GetRadius()); /// \todo Allow to define custom flags build.offMeshFlags_.Push(0x1); build.offMeshAreas_.Push(0); build.offMeshDir_.Push(connection->IsBidirectional() ? DT_OFFMESH_CON_BIDIR : 0); continue; } CollisionShape* shape = dynamic_cast<CollisionShape*>(geometryList[i].component_); if (shape) { switch (shape->GetShapeType()) { case SHAPE_TRIANGLEMESH: { Model* model = shape->GetModel(); if (!model) continue; unsigned lodLevel = shape->GetLodLevel(); for (unsigned j = 0; j < model->GetNumGeometries(); ++j) AddTriMeshGeometry(build, model->GetGeometry(j, lodLevel), transform); } break; case SHAPE_CONVEXHULL: { ConvexData* data = static_cast<ConvexData*>(shape->GetGeometryData()); if (!data) continue; unsigned numVertices = data->vertexCount_; unsigned numIndices = data->indexCount_; unsigned destVertexStart = build.vertices_.Size(); for (unsigned j = 0; j < numVertices; ++j) build.vertices_.Push(transform * data->vertexData_[j]); for (unsigned j = 0; j < numIndices; ++j) build.indices_.Push(data->indexData_[j] + destVertexStart); } break; case SHAPE_BOX: { unsigned destVertexStart = build.vertices_.Size(); build.vertices_.Push(transform * Vector3(-0.5f, 0.5f, -0.5f)); build.vertices_.Push(transform * Vector3(0.5f, 0.5f, -0.5f)); build.vertices_.Push(transform * Vector3(0.5f, -0.5f, -0.5f)); build.vertices_.Push(transform * Vector3(-0.5f, -0.5f, -0.5f)); build.vertices_.Push(transform * Vector3(-0.5f, 0.5f, 0.5f)); build.vertices_.Push(transform * Vector3(0.5f, 0.5f, 0.5f)); build.vertices_.Push(transform * Vector3(0.5f, -0.5f, 0.5f)); build.vertices_.Push(transform * Vector3(-0.5f, -0.5f, 0.5f)); const unsigned indices[] = { 0, 1, 2, 0, 2, 3, 1, 5, 6, 1, 6, 2, 4, 5, 1, 4, 1, 0, 5, 4, 7, 5, 7, 6, 4, 0, 3, 4, 3, 7, 1, 0, 4, 1, 4, 5 }; for (unsigned j = 0; j < 36; ++j) build.indices_.Push(indices[j] + destVertexStart); } break; default: break; } continue; } Drawable* drawable = dynamic_cast<Drawable*>(geometryList[i].component_); if (drawable) { const Vector<SourceBatch>& batches = drawable->GetBatches(); for (unsigned j = 0; j < batches.Size(); ++j) AddTriMeshGeometry(build, drawable->GetLodGeometry(j, geometryList[i].lodLevel_), transform); } } } }
/** Method to return an iterator pointing to the first item * in a given BoundingBox. */ iterator begin(const BoundingBox& bb) const { assert(!bb.empty()); return Iterator(this, bb, mc_.code(bb.min()), 0); }
inline bool contains (const BoundingBox & b) const { for (unsigned int i = 0; i < 3; i++) if (fabs (getMiddle (i) - b.getMiddle (i)) - BOUNDINGBOX_EPSILON > (getWHL (i) + b.getWHL (i)) / 2.0) return false; return true; }
/** Method to return an iterator pointing to "one past" * the last item in a given BoundingBox. */ iterator end(const BoundingBox& bb) const { assert(!bb.empty()); return Iterator(this, bb, mc_.code(bb.max())+1, 0); }
void Terrain::CreatePatchGeometry(TerrainPatch* patch) { PROFILE(CreatePatchGeometry); unsigned row = patchSize_ + 1; VertexBuffer* vertexBuffer = patch->GetVertexBuffer(); Geometry* geometry = patch->GetGeometry(); Geometry* maxLodGeometry = patch->GetMaxLodGeometry(); Geometry* minLodGeometry = patch->GetMinLodGeometry(); if (vertexBuffer->GetVertexCount() != row * row) vertexBuffer->SetSize(row * row, MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT); SharedArrayPtr<unsigned char> cpuVertexData(new unsigned char[row * row * sizeof(Vector3)]); float* vertexData = (float*)vertexBuffer->Lock(0, vertexBuffer->GetVertexCount()); float* positionData = (float*)cpuVertexData.Get(); BoundingBox box; if (vertexData) { const IntVector2& coords = patch->GetCoordinates(); for (int z1 = 0; z1 <= patchSize_; ++z1) { for (int x1 = 0; x1 <= patchSize_; ++x1) { int xPos = coords.x_ * patchSize_ + x1; int zPos = coords.y_ * patchSize_ + z1; // Position Vector3 position((float)x1 * spacing_.x_, GetRawHeight(xPos, zPos), (float)z1 * spacing_.z_); *vertexData++ = position.x_; *vertexData++ = position.y_; *vertexData++ = position.z_; *positionData++ = position.x_; *positionData++ = position.y_; *positionData++ = position.z_; box.Merge(position); // Normal Vector3 normal = GetRawNormal(xPos, zPos); *vertexData++ = normal.x_; *vertexData++ = normal.y_; *vertexData++ = normal.z_; // Texture coordinate Vector2 texCoord((float)xPos / (float)numVertices_.x_, 1.0f - (float)zPos / (float)numVertices_.y_); *vertexData++ = texCoord.x_; *vertexData++ = texCoord.y_; // Tangent Vector3 xyz = (Vector3::RIGHT - normal * normal.DotProduct(Vector3::RIGHT)).Normalized(); *vertexData++ = xyz.x_; *vertexData++ = xyz.y_; *vertexData++ = xyz.z_; *vertexData++ = 1.0f; } } vertexBuffer->Unlock(); vertexBuffer->ClearDataLost(); } patch->SetBoundingBox(box); if (drawRanges_.Size()) { unsigned lastDrawRange = drawRanges_.Size() - 1; geometry->SetIndexBuffer(indexBuffer_); geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false); geometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION); maxLodGeometry->SetIndexBuffer(indexBuffer_); maxLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false); maxLodGeometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION); minLodGeometry->SetIndexBuffer(indexBuffer_); minLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[lastDrawRange].first_, drawRanges_[lastDrawRange].second_, false); minLodGeometry->SetRawVertexData(cpuVertexData, sizeof(Vector3), MASK_POSITION); } // Offset the occlusion geometry by vertex spacing to reduce possibility of over-aggressive occlusion patch->SetOcclusionOffset(-0.5f * (spacing_.x_ + spacing_.z_)); patch->ResetLod(); }
ClusterVisualizer::ClusterVisualizer(string filename) { ifstream in(filename.c_str()); // Check! if(!in.good()) return; MeshCluster* cluster = new MeshCluster; // Read sub meshes while(in.good()) { string cluster_name; int num_faces; int num_vertices; // Read 'header' in >> cluster_name; in >> num_faces >> num_vertices; BoundingBox<Vertex<float> > bb; // Alloc buffers if(num_faces && num_vertices) { floatArr vertices(new float[3 * num_vertices]); floatArr normals(new float[3 * num_vertices]); ucharArr colors(new uchar[3 * num_vertices]); uintArr indices(new uint[3 * num_faces]); // Read indices for(int i = 0; i < num_faces; i++) { int pos = 3 * i; uint a, b, c; in >> a >> b >> c; indices[pos ] = a; indices[pos + 1] = b; indices[pos + 2] = c; } // Read vertices, normals and colors for(int i = 0; i < num_vertices; i++) { int pos = 3 * i; float x, y, z, nx, ny, nz; int r, g, b; in >> x >> y >> z >> nx >> ny >> nz >> r >> g >> b; vertices[pos ] = x; vertices[pos + 1] = y; vertices[pos + 2] = z; normals[pos ] = nx; normals[pos + 1] = ny; normals[pos + 2] = nz; colors[pos ] = (uchar)r; colors[pos + 1] = (uchar)g; colors[pos + 2] = (uchar)b; bb.expand(x, y, z); } // Create Buffer MeshBufferPtr* buffer = new MeshBufferPtr(new MeshBuffer); buffer->get()->setVertexArray(vertices, num_vertices); buffer->get()->setVertexNormalArray(normals, num_vertices); buffer->get()->setVertexColorArray(colors, num_vertices); buffer->get()->setFaceArray(indices, num_faces); cluster->boundingBox()->expand(bb); cluster->addMesh(*buffer, cluster_name); } }