bool TableObjectDetector<PointType> :: detect(PointCloudConstPtr cloud) { m_object_clusters.clear(); initialize(); // ---[ Convert the dataset cloud_ = cloud; // ---[ Create the voxel grid pcl::PointCloud<Point> cloud_filtered; pass_.setInputCloud (cloud_); pass_.filter (cloud_filtered); cloud_filtered_.reset (new pcl::PointCloud<Point> (cloud_filtered)); pcl::PointCloud<Point> cloud_downsampled; grid_.setInputCloud (cloud_filtered_); grid_.filter (cloud_downsampled); cloud_downsampled_.reset (new pcl::PointCloud<Point> (cloud_downsampled)); if ((int) cloud_filtered_->points.size () < k_) { // This means that filtering returned very few points return false; } // ---[ Estimate the point normals pcl::PointCloud<pcl::Normal> cloud_normals; n3d_.setInputCloud (cloud_downsampled_); n3d_.compute (cloud_normals); cloud_normals_.reset (new pcl::PointCloud<pcl::Normal> (cloud_normals)); // ---[ Perform segmentation pcl::PointIndices table_inliers; pcl::ModelCoefficients table_coefficients; seg_.setInputCloud (cloud_downsampled_); seg_.setInputNormals (cloud_normals_); seg_.segment (table_inliers, table_coefficients); table_inliers_.reset (new pcl::PointIndices (table_inliers)); table_coefficients_.reset (new pcl::ModelCoefficients (table_coefficients)); if (table_inliers_->indices.size () == 0) return false; m_plane = Plane (table_coefficients.values[0], table_coefficients.values[1], table_coefficients.values[2], table_coefficients.values[3]); // ---[ Extract the table pcl::PointCloud<Point> table_projected; proj_.setInputCloud (cloud_downsampled_); proj_.setIndices (table_inliers_); proj_.setModelCoefficients (table_coefficients_); proj_.filter (table_projected); table_projected_.reset (new pcl::PointCloud<Point> (table_projected)); // ---[ Estimate the convex hull pcl::PointCloud<Point> table_hull; hull_.setDimension(2); hull_.setInputCloud (table_projected_); hull_.reconstruct (table_hull); table_hull_.reset (new pcl::PointCloud<Point> (table_hull)); // ---[ Get the objects on top of the table pcl::PointIndices cloud_object_indices; prism_.setInputCloud (cloud_filtered_); prism_.setInputPlanarHull (table_hull_); prism_.segment (cloud_object_indices); pcl::PointCloud<Point> cloud_objects; pcl::ExtractIndices<Point> extract_object_indices; extract_object_indices.setInputCloud (cloud_filtered_); extract_object_indices.setIndices (boost::make_shared<const pcl::PointIndices> (cloud_object_indices)); extract_object_indices.filter (cloud_objects); cloud_objects_.reset (new pcl::PointCloud<Point> (cloud_objects)); if (cloud_objects.points.size () == 0) return false; // ---[ Downsample the points #if 0 pcl::PointCloud<Point> cloud_objects_downsampled; grid_objects_.setInputCloud (cloud_objects_); grid_objects_.filter (cloud_objects_downsampled); cloud_objects_downsampled_.reset (new pcl::PointCloud<Point> (cloud_objects_downsampled)); #endif // ---[ Split the objects into Euclidean clusters std::vector< pcl::PointIndices > object_clusters; cluster_.setInputCloud (cloud_objects_); cluster_.extract (object_clusters); for (size_t i = 0; i < object_clusters.size (); ++i) { std::vector <PointType, Eigen::aligned_allocator<PointType>> object_points; for (size_t k = 0; k < object_clusters[i].indices.size(); ++k) { int index = object_clusters[i].indices[k]; Point p = cloud_objects_->points[index]; object_points.push_back(p); } float min_dist_to_plane = FLT_MAX; for (int j = 0; j < object_points.size(); ++j) { pcl::PointXYZ pobj; pobj.x = object_points[j].x; pobj.y = object_points[j].y; pobj.z = object_points[j].z; min_dist_to_plane = std::min(plane().distanceToPlane(pobj), min_dist_to_plane); } if (min_dist_to_plane > m_max_dist_to_plane) continue; m_object_clusters.push_back(object_points); } return true; }
Plane Plane::Normalize(const Plane plane) { float magnitude = 1.0f / Math::Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z)); return Plane(plane.Normal.X * magnitude, plane.Normal.Y * magnitude, plane.Normal.Z * magnitude, plane.D * magnitude); }
Plane Plane::reversePlane() const { return Plane(-m_a, -m_b, -m_c, -m_d); }
Variant::Variant(const Plane& p_plane) { type=PLANE; memnew_placement( _data._mem, Plane( p_plane ) ); }
void Variant::reference(const Variant& p_variant) { if (this == &p_variant) return; clear(); type=p_variant.type; switch( p_variant.type ) { case NIL: { // none } break; // atomic types case BOOL: { _data._bool=p_variant._data._bool; } break; case INT: { _data._int=p_variant._data._int; } break; case REAL: { _data._real=p_variant._data._real; } break; case STRING: { memnew_placement( _data._mem, String( *reinterpret_cast<const String*>(p_variant._data._mem) ) ); } break; // math types case VECTOR2: { memnew_placement( _data._mem, Vector2( *reinterpret_cast<const Vector2*>(p_variant._data._mem) ) ); } break; case RECT2: { memnew_placement( _data._mem, Rect2( *reinterpret_cast<const Rect2*>(p_variant._data._mem) ) ); } break; case MATRIX32: { _data._matrix32 = memnew( Matrix32( *p_variant._data._matrix32 ) ); } break; case VECTOR3: { memnew_placement( _data._mem, Vector3( *reinterpret_cast<const Vector3*>(p_variant._data._mem) ) ); } break; case PLANE: { memnew_placement( _data._mem, Plane( *reinterpret_cast<const Plane*>(p_variant._data._mem) ) ); } break; /* case QUAT: { } break;*/ case _AABB: { _data._aabb = memnew( AABB( *p_variant._data._aabb ) ); } break; case QUAT: { memnew_placement( _data._mem, Quat( *reinterpret_cast<const Quat*>(p_variant._data._mem) ) ); } break; case MATRIX3: { _data._matrix3 = memnew( Matrix3( *p_variant._data._matrix3 ) ); } break; case TRANSFORM: { _data._transform = memnew( Transform( *p_variant._data._transform ) ); } break; // misc types case COLOR: { memnew_placement( _data._mem, Color( *reinterpret_cast<const Color*>(p_variant._data._mem) ) ); } break; case IMAGE: { _data._image = memnew( Image( *p_variant._data._image ) ); } break; case _RID: { memnew_placement( _data._mem, RID( *reinterpret_cast<const RID*>(p_variant._data._mem) ) ); } break; case OBJECT: { memnew_placement( _data._mem, ObjData( p_variant._get_obj() ) ); } break; case NODE_PATH: { memnew_placement( _data._mem, NodePath( *reinterpret_cast<const NodePath*>(p_variant._data._mem) ) ); } break; case INPUT_EVENT: { _data._input_event= memnew( InputEvent( *p_variant._data._input_event ) ); } break; case DICTIONARY: { memnew_placement( _data._mem, Dictionary( *reinterpret_cast<const Dictionary*>(p_variant._data._mem) ) ); } break; case ARRAY: { memnew_placement( _data._mem, Array ( *reinterpret_cast<const Array*>(p_variant._data._mem) ) ); } break; // arrays case RAW_ARRAY: { memnew_placement( _data._mem, DVector<uint8_t> ( *reinterpret_cast<const DVector<uint8_t>*>(p_variant._data._mem) ) ); } break; case INT_ARRAY: { memnew_placement( _data._mem, DVector<int> ( *reinterpret_cast<const DVector<int>*>(p_variant._data._mem) ) ); } break; case REAL_ARRAY: { memnew_placement( _data._mem, DVector<real_t> ( *reinterpret_cast<const DVector<real_t>*>(p_variant._data._mem) ) ); } break; case STRING_ARRAY: { memnew_placement( _data._mem, DVector<String> ( *reinterpret_cast<const DVector<String>*>(p_variant._data._mem) ) ); } break; case VECTOR2_ARRAY: { memnew_placement( _data._mem, DVector<Vector2> ( *reinterpret_cast<const DVector<Vector2>*>(p_variant._data._mem) ) ); } break; case VECTOR3_ARRAY: { memnew_placement( _data._mem, DVector<Vector3> ( *reinterpret_cast<const DVector<Vector3>*>(p_variant._data._mem) ) ); } break; case COLOR_ARRAY: { memnew_placement( _data._mem, DVector<Color> ( *reinterpret_cast<const DVector<Color>*>(p_variant._data._mem) ) ); } break; default: {} } }
PlaneShape::PlaneShape() : Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_PLANE)) { set_plane(Plane(0, 1, 0, 0)); }
void CameraPerspective::CameraBound::calculate(const CameraPerspective* cam) { // Calc frustum const mat44& matrix(cam->getViewProjection()); m_Frustum.getPlaneForEdit(FrustumPlane_LeftClipPlane) = Plane( matrix(3, 0) + matrix(0, 0), matrix(3, 1) + matrix(0, 1), matrix(3, 2) + matrix(0, 2), matrix(3, 3) + matrix(0, 3)); m_Frustum.getPlaneForEdit(FrustumPlane_RightClipPlane) = Plane( matrix(3, 0) - matrix(0, 0), matrix(3, 1) - matrix(0, 1), matrix(3, 2) - matrix(0, 2), matrix(3, 3) - matrix(0, 3)); m_Frustum.getPlaneForEdit(FrustumPlane_TopClipPlane) = Plane( matrix(3, 0) - matrix(1, 0), matrix(3, 1) - matrix(1, 1), matrix(3, 2) - matrix(1, 2), matrix(3, 3) - matrix(1, 3)); m_Frustum.getPlaneForEdit(FrustumPlane_BottomClipPlane) = Plane( matrix(3, 0) + matrix(1, 0), matrix(3, 1) + matrix(1, 1), matrix(3, 2) + matrix(1, 2), matrix(3, 3) + matrix(1, 3)); m_Frustum.getPlaneForEdit(FrustumPlane_NearClipPlane) = Plane( matrix(3, 0) + matrix(2, 0), matrix(3, 1) + matrix(2, 1), matrix(3, 2) + matrix(2, 2), matrix(3, 3) + matrix(2, 3)); m_Frustum.getPlaneForEdit(FrustumPlane_FarClipPlane) = Plane( matrix(3, 0) - matrix(2, 0), matrix(3, 1) - matrix(2, 1), matrix(3, 2) - matrix(2, 2), matrix(3, 3) - matrix(2, 3)); // calculate sphere float nearClip(cam->getNearClip()); float farClip(cam->getFarClip()); float tanFov(tan(cam->getFov() * 0.5f)); const vec3& pos(cam->getPosition()); const vec3& look(cam->getLook()); float viewLength(farClip - nearClip); float halfHeight(farClip * tanFov); float halfWidth(halfHeight * cam->getAspectRatio()); vec3 halfWayPoint(0.0f, 0.0f, viewLength * 0.5f); vec3 farCorner(halfWidth, halfHeight, viewLength); vec3 diff(halfWayPoint - farCorner); m_Sphere.setRadius(length(diff)); m_Sphere.setPosition(pos + look * halfWayPoint.z); // calculate cone float corner(sqrt(halfWidth * halfWidth + halfHeight * halfHeight)); float fov(atan(corner / farClip) * 2.0f); m_Cone.setPosition(pos); m_Cone.setAxis(look); m_Cone.setFov(fov); m_Cone.setAxisLength(farClip); }
Plane MeshDataTool::get_vertex_tangent(int p_idx) const{ ERR_FAIL_INDEX_V(p_idx,vertices.size(),Plane()); return vertices[p_idx].tangent; }
Error MeshDataTool::create_from_surface(const Ref<Mesh>& p_mesh,int p_surface) { ERR_FAIL_COND_V(p_mesh.is_null(),ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_mesh.is_null(),ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_mesh->surface_get_primitive_type(p_surface)!=Mesh::PRIMITIVE_TRIANGLES,ERR_INVALID_PARAMETER); Array arrays = p_mesh->surface_get_arrays(p_surface); ERR_FAIL_COND_V( arrays.empty(), ERR_INVALID_PARAMETER ); DVector<Vector3> varray = arrays[Mesh::ARRAY_VERTEX]; int vcount = varray.size(); ERR_FAIL_COND_V( vcount == 0, ERR_INVALID_PARAMETER); clear(); format = p_mesh->surface_get_format(p_surface); material=p_mesh->surface_get_material(p_surface); DVector<Vector3>::Read vr = varray.read(); DVector<Vector3>::Read nr; if (arrays[Mesh::ARRAY_NORMAL].get_type()!=Variant::NIL) nr = arrays[Mesh::ARRAY_NORMAL].operator DVector<Vector3>().read(); DVector<real_t>::Read ta; if (arrays[Mesh::ARRAY_TANGENT].get_type()!=Variant::NIL) ta = arrays[Mesh::ARRAY_TANGENT].operator DVector<real_t>().read(); DVector<Vector2>::Read uv; if (arrays[Mesh::ARRAY_TEX_UV].get_type()!=Variant::NIL) uv = arrays[Mesh::ARRAY_TEX_UV].operator DVector<Vector2>().read(); DVector<Vector2>::Read uv2; if (arrays[Mesh::ARRAY_TEX_UV2].get_type()!=Variant::NIL) uv2 = arrays[Mesh::ARRAY_TEX_UV2].operator DVector<Vector2>().read(); DVector<Color>::Read col; if (arrays[Mesh::ARRAY_COLOR].get_type()!=Variant::NIL) col = arrays[Mesh::ARRAY_COLOR].operator DVector<Color>().read(); DVector<real_t>::Read bo; if (arrays[Mesh::ARRAY_BONES].get_type()!=Variant::NIL) bo = arrays[Mesh::ARRAY_BONES].operator DVector<real_t>().read(); DVector<real_t>::Read we; if (arrays[Mesh::ARRAY_WEIGHTS].get_type()!=Variant::NIL) we = arrays[Mesh::ARRAY_WEIGHTS].operator DVector<real_t>().read(); vertices.resize(vcount); for(int i=0;i<vcount;i++) { Vertex v; v.vertex=vr[i]; if (nr.ptr()) v.normal=nr[i]; if (ta.ptr()) v.tangent=Plane(ta[i*4+0],ta[i*4+1],ta[i*4+2],ta[i*4+3]); if (uv.ptr()) v.uv=uv[i]; if (uv2.ptr()) v.uv2=uv2[i]; if (col.ptr()) v.color=col[i]; if (we.ptr()) { v.weights.push_back(we[i*4+0]); v.weights.push_back(we[i*4+1]); v.weights.push_back(we[i*4+2]); v.weights.push_back(we[i*4+3]); } if (bo.ptr()) { v.bones.push_back(bo[i*4+0]); v.bones.push_back(bo[i*4+1]); v.bones.push_back(bo[i*4+2]); v.bones.push_back(bo[i*4+3]); } vertices[i]=v; } DVector<int> indices; if (arrays[Mesh::ARRAY_INDEX].get_type()!=Variant::NIL) { indices = arrays[Mesh::ARRAY_INDEX]; } else { //make code simpler indices.resize(vcount); DVector<int>::Write iw=indices.write(); for(int i=0;i<vcount;i++) iw[i]=i; } int icount=indices.size(); DVector<int>::Read r = indices.read(); Map<Point2i,int> edge_indices; for(int i=0;i<icount;i+=3) { Vertex*v[3]={ &vertices[r[i+0]], &vertices[r[i+1]], &vertices[r[i+2]] }; int fidx=faces.size(); Face face; for(int j=0;j<3;j++) { face.v[j]=r[i+j]; Point2i edge(r[i+j],r[i+(j+1)%3]); if (edge.x > edge.y) { SWAP(edge.x,edge.y); } if (edge_indices.has(edge)) { face.edges[j]=edge_indices[edge]; } else { face.edges[j]=edge_indices.size(); edge_indices[edge]=face.edges[j]; Edge e; e.vertex[0]=edge.x; e.vertex[1]=edge.y; edges.push_back(e); } edges[face.edges[j]].faces.push_back(fidx); v[j]->faces.push_back(fidx); v[j]->edges.push_back(face.edges[j]); } faces.push_back(face); } return OK; }
bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis) { if (p_shape_A->is_concave()) return false; if (p_shape_B->get_type()==PhysicsServer::SHAPE_PLANE) { Vector3 a,b; bool col = solve_distance_plane(p_shape_B,p_transform_B,p_shape_A,p_transform_A,a,b); r_point_A=b; r_point_B=a; return !col; } else if (p_shape_B->is_concave()) { if (p_shape_A->is_concave()) return false; const ConcaveShapeSW *concave_B=static_cast<const ConcaveShapeSW*>(p_shape_B); _ConcaveCollisionInfo cinfo; cinfo.transform_A=&p_transform_A; cinfo.shape_A=p_shape_A; cinfo.transform_B=&p_transform_B; cinfo.result_callback=NULL; cinfo.userdata=NULL; cinfo.swap_result=false; cinfo.collided=false; cinfo.collisions=0; cinfo.aabb_tests=0; cinfo.tested=false; Transform rel_transform = p_transform_A; rel_transform.origin-=p_transform_B.origin; //quickly compute a local AABB bool use_cc_hint=p_concave_hint!=AABB(); AABB cc_hint_aabb; if (use_cc_hint) { cc_hint_aabb=p_concave_hint; cc_hint_aabb.pos-=p_transform_B.origin; } AABB local_aabb; for(int i=0;i<3;i++) { Vector3 axis( p_transform_B.basis.get_axis(i) ); float axis_scale = 1.0/axis.length(); axis*=axis_scale; float smin,smax; if (use_cc_hint) { cc_hint_aabb.project_range_in_plane(Plane(axis,0),smin,smax); } else { p_shape_A->project_range(axis,rel_transform,smin,smax); } smin*=axis_scale; smax*=axis_scale; local_aabb.pos[i]=smin; local_aabb.size[i]=smax-smin; } concave_B->cull(local_aabb,concave_distance_callback,&cinfo); if (!cinfo.collided) { // print_line(itos(cinfo.tested)); r_point_A=cinfo.close_A; r_point_B=cinfo.close_B; } //print_line("DIST AABB TESTS: "+itos(cinfo.aabb_tests)); return !cinfo.collided; } else { return gjk_epa_calculate_distance(p_shape_A,p_transform_A,p_shape_B,p_transform_B,r_point_A,r_point_B); //should pass sepaxis.. } return false; }
void Frustum::rebuild() { // Rebuilds the clipping planes as well as the near and far corners. const Math::Matrix4x4 viewProjMatrix = m_ProjMatrix * m_ViewMatrix; const Math::Matrix4x4 invViewProjMatrix = viewProjMatrix.getInverse(); //------------------------------------------------------------ // Set corners in NDC-space Math::Vector4f nearLowerLeft = Math::Vector4f(-1.0f, -1.0f, 0.0f, 1.0f); Math::Vector4f nearLowerRight = Math::Vector4f( 1.0f, -1.0f, 0.0f, 1.0f); Math::Vector4f nearUpperRight = Math::Vector4f( 1.0f, 1.0f, 0.0f, 1.0f); Math::Vector4f nearUpperLeft = Math::Vector4f(-1.0f, 1.0f, 0.0f, 1.0f); Math::Vector4f farLowerLeft = Math::Vector4f(-1.0f, -1.0f, 1.0f, 1.0f); Math::Vector4f farLowerRight = Math::Vector4f( 1.0f, -1.0f, 1.0f, 1.0f); Math::Vector4f farUpperRight = Math::Vector4f( 1.0f, 1.0f, 1.0f, 1.0f); Math::Vector4f farUpperLeft = Math::Vector4f(-1.0f, 1.0f, 1.0f, 1.0f); //------------------------------------------------------------ // Mutiply by inverse view-projection matrix nearLowerLeft = invViewProjMatrix * nearLowerLeft; nearLowerRight = invViewProjMatrix * nearLowerRight; nearUpperRight = invViewProjMatrix * nearUpperRight; nearUpperLeft = invViewProjMatrix * nearUpperLeft; farLowerLeft = invViewProjMatrix * farLowerLeft; farLowerRight = invViewProjMatrix * farLowerRight; farUpperRight = invViewProjMatrix * farUpperRight; farUpperLeft = invViewProjMatrix * farUpperLeft; //------------------------------------------------------------ // Divide by w term nearLowerLeft /= nearLowerLeft.w; nearLowerRight /= nearLowerRight.w; nearUpperRight /= nearUpperRight.w; nearUpperLeft /= nearUpperLeft.w; farLowerLeft /= farLowerLeft.w; farLowerRight /= farLowerRight.w; farUpperRight /= farUpperRight.w; farUpperLeft /= farUpperLeft.w; //------------------------------------------------------------ // Set world-space corners m_NearCorners[0] = nearLowerLeft.xyz(); m_NearCorners[1] = nearLowerRight.xyz(); m_NearCorners[2] = nearUpperRight.xyz(); m_NearCorners[3] = nearUpperLeft.xyz(); m_FarCorners[0] = farLowerLeft.xyz(); m_FarCorners[1] = farLowerRight.xyz(); m_FarCorners[2] = farUpperRight.xyz(); m_FarCorners[3] = farUpperLeft.xyz(); //------------------------------------------------------------ // Build bounding planes m_LeftPlane = Plane(m_NearCorners[0], m_NearCorners[3], m_FarCorners[3]); m_TopPlane = Plane(m_NearCorners[3], m_NearCorners[2], m_FarCorners[2]); m_RightPlane = Plane(m_NearCorners[1], m_FarCorners[1], m_FarCorners[2]); m_BottomPlane = Plane(m_NearCorners[0], m_FarCorners[0], m_FarCorners[1]); m_NearPlane = Plane(m_NearCorners[0], m_NearCorners[1], m_NearCorners[2]); m_FarPlane = Plane(m_FarCorners[0], m_FarCorners[3], m_FarCorners[2]); }
//----------------------------------------------------------------------- const PlaneBoundedVolumeList& Light::_getFrustumClipVolumes(const Camera* const cam) const { // Homogenous light position Vector4 lightPos = getAs4DVector(); // 3D version (not the same as _getDerivedPosition, is -direction for // directional lights) Vector3 lightPos3 = Vector3(lightPos.x, lightPos.y, lightPos.z); const Vector3 *clockwiseVerts[4]; // Get worldspace frustum corners const Vector3* corners = cam->getWorldSpaceCorners(); int windingPt0 = cam->isReflected() ? 1 : 0; int windingPt1 = cam->isReflected() ? 0 : 1; bool infiniteViewDistance = (cam->getFarClipDistance() == 0); Vector3 notSoFarCorners[4]; if(infiniteViewDistance) { Vector3 camPosition = cam->getRealPosition(); notSoFarCorners[0] = corners[0] + corners[0] - camPosition; notSoFarCorners[1] = corners[1] + corners[1] - camPosition; notSoFarCorners[2] = corners[2] + corners[2] - camPosition; notSoFarCorners[3] = corners[3] + corners[3] - camPosition; } mFrustumClipVolumes.clear(); for (unsigned short n = 0; n < 6; ++n) { // Skip far plane if infinite view frustum if (infiniteViewDistance && n == FRUSTUM_PLANE_FAR) continue; const Plane& plane = cam->getFrustumPlane(n); Vector4 planeVec(plane.normal.x, plane.normal.y, plane.normal.z, plane.d); // planes face inwards, we need to know if light is on negative side Real d = planeVec.dotProduct(lightPos); if (d < -1e-06) { // Ok, this is a valid one // clockwise verts mean we can cross-product and always get normals // facing into the volume we create mFrustumClipVolumes.push_back(PlaneBoundedVolume()); PlaneBoundedVolume& vol = mFrustumClipVolumes.back(); switch(n) { case(FRUSTUM_PLANE_NEAR): clockwiseVerts[0] = corners + 3; clockwiseVerts[1] = corners + 2; clockwiseVerts[2] = corners + 1; clockwiseVerts[3] = corners + 0; break; case(FRUSTUM_PLANE_FAR): clockwiseVerts[0] = corners + 7; clockwiseVerts[1] = corners + 6; clockwiseVerts[2] = corners + 5; clockwiseVerts[3] = corners + 4; break; case(FRUSTUM_PLANE_LEFT): clockwiseVerts[0] = infiniteViewDistance ? notSoFarCorners + 1 : corners + 5; clockwiseVerts[1] = corners + 1; clockwiseVerts[2] = corners + 2; clockwiseVerts[3] = infiniteViewDistance ? notSoFarCorners + 2 : corners + 6; break; case(FRUSTUM_PLANE_RIGHT): clockwiseVerts[0] = infiniteViewDistance ? notSoFarCorners + 3 : corners + 7; clockwiseVerts[1] = corners + 3; clockwiseVerts[2] = corners + 0; clockwiseVerts[3] = infiniteViewDistance ? notSoFarCorners + 0 : corners + 4; break; case(FRUSTUM_PLANE_TOP): clockwiseVerts[0] = infiniteViewDistance ? notSoFarCorners + 0 : corners + 4; clockwiseVerts[1] = corners + 0; clockwiseVerts[2] = corners + 1; clockwiseVerts[3] = infiniteViewDistance ? notSoFarCorners + 1 : corners + 5; break; case(FRUSTUM_PLANE_BOTTOM): clockwiseVerts[0] = infiniteViewDistance ? notSoFarCorners + 2 : corners + 6; clockwiseVerts[1] = corners + 2; clockwiseVerts[2] = corners + 3; clockwiseVerts[3] = infiniteViewDistance ? notSoFarCorners + 3 : corners + 7; break; }; // Build a volume // Iterate over world points and form side planes Vector3 normal; Vector3 lightDir; unsigned int infiniteViewDistanceInt = infiniteViewDistance ? 1 : 0; for (unsigned int i = 0; i < 4 - infiniteViewDistanceInt; ++i) { // Figure out light dir lightDir = lightPos3 - (*(clockwiseVerts[i]) * lightPos.w); Vector3 edgeDir = *(clockwiseVerts[(i+windingPt1)%4]) - *(clockwiseVerts[(i+windingPt0)%4]); // Cross with anticlockwise corner, therefore normal points in normal = edgeDir.crossProduct(lightDir); normal.normalise(); vol.planes.push_back(Plane(normal, *(clockwiseVerts[i]))); } // Now do the near plane (this is the plane of the side we're // talking about, with the normal inverted (d is already interpreted as -ve) vol.planes.push_back( Plane(-plane.normal, plane.d) ); // Finally, for a point/spot light we can add a sixth plane // This prevents false positives from behind the light if (mLightType != LT_DIRECTIONAL) { // re-use our own plane normal vol.planes.push_back(Plane(plane.normal, lightPos3)); } } } return mFrustumClipVolumes; }
//----------------------------------------------------------------------- const PlaneBoundedVolume& Light::_getNearClipVolume(const Camera* const cam) const { // First check if the light is close to the near plane, since // in this case we have to build a degenerate clip volume mNearClipVolume.planes.clear(); mNearClipVolume.outside = Plane::NEGATIVE_SIDE; Real n = cam->getNearClipDistance(); // Homogenous position Vector4 lightPos = getAs4DVector(); // 3D version (not the same as _getDerivedPosition, is -direction for // directional lights) Vector3 lightPos3 = Vector3(lightPos.x, lightPos.y, lightPos.z); // Get eye-space light position // use 4D vector so directional lights still work Vector4 eyeSpaceLight = cam->getViewMatrix() * lightPos; // Find distance to light, project onto -Z axis Real d = eyeSpaceLight.dotProduct( Vector4(0, 0, -1, -n) ); #define THRESHOLD 1e-6 if (d > THRESHOLD || d < -THRESHOLD) { // light is not too close to the near plane // First find the worldspace positions of the corners of the viewport const Vector3 *corner = cam->getWorldSpaceCorners(); int winding = (d < 0) ^ cam->isReflected() ? +1 : -1; // Iterate over world points and form side planes Vector3 normal; Vector3 lightDir; for (unsigned int i = 0; i < 4; ++i) { // Figure out light dir lightDir = lightPos3 - (corner[i] * lightPos.w); // Cross with anticlockwise corner, therefore normal points in normal = (corner[i] - corner[(i+winding)%4]) .crossProduct(lightDir); normal.normalise(); mNearClipVolume.planes.push_back(Plane(normal, corner[i])); } // Now do the near plane plane normal = cam->getFrustumPlane(FRUSTUM_PLANE_NEAR).normal; if (d < 0) { // Behind near plane normal = -normal; } const Vector3& cameraPos = cam->getDerivedPosition(); mNearClipVolume.planes.push_back(Plane(normal, cameraPos)); // Finally, for a point/spot light we can add a sixth plane // This prevents false positives from behind the light if (mLightType != LT_DIRECTIONAL) { // Direction from light perpendicular to near plane mNearClipVolume.planes.push_back(Plane(-normal, lightPos3)); } } else { // light is close to being on the near plane // degenerate volume including the entire scene // we will always require light / dark caps mNearClipVolume.planes.push_back(Plane(Vector3::UNIT_Z, -n)); mNearClipVolume.planes.push_back(Plane(-Vector3::UNIT_Z, n)); } return mNearClipVolume; }
Plane AABB::FacePlane(int faceIndex) const { assume(0 <= faceIndex && faceIndex <= 5); return Plane(FaceCenterPoint(faceIndex), FaceNormal(faceIndex)); }
void BakedLight::_plot_face(int p_idx, int p_level, const Vector3 *p_vtx, const Vector2 *p_uv, const MaterialCache &p_material, const Rect3 &p_aabb) { if (p_level == cell_subdiv - 1) { //plot the face by guessing it's albedo and emission value //find best axis to map to, for scanning values int closest_axis; float closest_dot; Vector3 normal = Plane(p_vtx[0], p_vtx[1], p_vtx[2]).normal; for (int i = 0; i < 3; i++) { Vector3 axis; axis[i] = 1.0; float dot = ABS(normal.dot(axis)); if (i == 0 || dot > closest_dot) { closest_axis = i; closest_dot = dot; } } Vector3 axis; axis[closest_axis] = 1.0; Vector3 t1; t1[(closest_axis + 1) % 3] = 1.0; Vector3 t2; t2[(closest_axis + 2) % 3] = 1.0; t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width); t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width); Color albedo_accum; Color emission_accum; float alpha = 0.0; //map to a grid average in the best axis for this face for (int i = 0; i < color_scan_cell_width; i++) { Vector3 ofs_i = float(i) * t1; for (int j = 0; j < color_scan_cell_width; j++) { Vector3 ofs_j = float(j) * t2; Vector3 from = p_aabb.pos + ofs_i + ofs_j; Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis]; Vector3 half = (to - from) * 0.5; //is in this cell? if (!fast_tri_box_overlap(from + half, half, p_vtx)) { continue; //face does not span this cell } //go from -size to +size*2 to avoid skipping collisions Vector3 ray_from = from + (t1 + t2) * 0.5 - axis * p_aabb.size[closest_axis]; Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis] * 2; Vector3 intersection; if (!Geometry::ray_intersects_triangle(ray_from, ray_to, p_vtx[0], p_vtx[1], p_vtx[2], &intersection)) { //no intersect? look in edges float closest_dist = 1e20; for (int j = 0; j < 3; j++) { Vector3 c; Vector3 inters; Geometry::get_closest_points_between_segments(p_vtx[j], p_vtx[(j + 1) % 3], ray_from, ray_to, inters, c); float d = c.distance_to(intersection); if (j == 0 || d < closest_dist) { closest_dist = d; intersection = inters; } } } Vector2 uv = get_uv(intersection, p_vtx, p_uv); int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); int ofs = uv_y * bake_texture_size + uv_x; albedo_accum.r += p_material.albedo[ofs].r; albedo_accum.g += p_material.albedo[ofs].g; albedo_accum.b += p_material.albedo[ofs].b; albedo_accum.a += p_material.albedo[ofs].a; emission_accum.r += p_material.emission[ofs].r; emission_accum.g += p_material.emission[ofs].g; emission_accum.b += p_material.emission[ofs].b; alpha += 1.0; } } if (alpha == 0) { //could not in any way get texture information.. so use closest point to center Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]); Vector3 inters = f.get_closest_point_to(p_aabb.pos + p_aabb.size * 0.5); Vector2 uv = get_uv(inters, p_vtx, p_uv); int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); int ofs = uv_y * bake_texture_size + uv_x; alpha = 1.0 / (color_scan_cell_width * color_scan_cell_width); albedo_accum.r = p_material.albedo[ofs].r * alpha; albedo_accum.g = p_material.albedo[ofs].g * alpha; albedo_accum.b = p_material.albedo[ofs].b * alpha; albedo_accum.a = p_material.albedo[ofs].a * alpha; emission_accum.r = p_material.emission[ofs].r * alpha; emission_accum.g = p_material.emission[ofs].g * alpha; emission_accum.b = p_material.emission[ofs].b * alpha; zero_alphas++; } else { float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width); alpha *= accdiv; albedo_accum.r *= accdiv; albedo_accum.g *= accdiv; albedo_accum.b *= accdiv; albedo_accum.a *= accdiv; emission_accum.r *= accdiv; emission_accum.g *= accdiv; emission_accum.b *= accdiv; } //put this temporarily here, corrected in a later step bake_cells_write[p_idx].albedo[0] += albedo_accum.r; bake_cells_write[p_idx].albedo[1] += albedo_accum.g; bake_cells_write[p_idx].albedo[2] += albedo_accum.b; bake_cells_write[p_idx].light[0] += emission_accum.r; bake_cells_write[p_idx].light[1] += emission_accum.g; bake_cells_write[p_idx].light[2] += emission_accum.b; bake_cells_write[p_idx].alpha += alpha; static const Vector3 side_normals[6] = { Vector3(-1, 0, 0), Vector3(1, 0, 0), Vector3(0, -1, 0), Vector3(0, 1, 0), Vector3(0, 0, -1), Vector3(0, 0, 1), }; for (int i = 0; i < 6; i++) { if (normal.dot(side_normals[i]) > CMP_EPSILON) { bake_cells_write[p_idx].used_sides |= (1 << i); } } } else { //go down for (int i = 0; i < 8; i++) { Rect3 aabb = p_aabb; aabb.size *= 0.5; if (i & 1) aabb.pos.x += aabb.size.x; if (i & 2) aabb.pos.y += aabb.size.y; if (i & 4) aabb.pos.z += aabb.size.z; { Rect3 test_aabb = aabb; //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test if (!fast_tri_box_overlap(test_aabb.pos + qsize, qsize, p_vtx)) { //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { //does not fit in child, go on continue; } } if (bake_cells_write[p_idx].childs[i] == CHILD_EMPTY) { //sub cell must be created if (bake_cells_used == (1 << bake_cells_alloc)) { //exhausted cells, creating more space bake_cells_alloc++; bake_cells_write = PoolVector<BakeCell>::Write(); bake_cells.resize(1 << bake_cells_alloc); bake_cells_write = bake_cells.write(); } bake_cells_write[p_idx].childs[i] = bake_cells_used; bake_cells_level_used[p_level + 1]++; bake_cells_used++; } _plot_face(bake_cells_write[p_idx].childs[i], p_level + 1, p_vtx, p_uv, p_material, aabb); } } }
Object* Primitives::Plane(int iSegments, float fRadius) { return Plane(iSegments, iSegments, fRadius, fRadius); }
void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const Vector3 *p_vtx, const Vector2* p_uv, const Baker::MaterialCache& p_material, const Rect3 &p_aabb,Baker *p_baker) { if (p_level==p_baker->cell_subdiv-1) { //plot the face by guessing it's albedo and emission value //find best axis to map to, for scanning values int closest_axis; float closest_dot; Vector3 normal = Plane(p_vtx[0],p_vtx[1],p_vtx[2]).normal; for(int i=0;i<3;i++) { Vector3 axis; axis[i]=1.0; float dot=ABS(normal.dot(axis)); if (i==0 || dot>closest_dot) { closest_axis=i; closest_dot=dot; } } Vector3 axis; axis[closest_axis]=1.0; Vector3 t1; t1[(closest_axis+1)%3]=1.0; Vector3 t2; t2[(closest_axis+2)%3]=1.0; t1*=p_aabb.size[(closest_axis+1)%3]/float(color_scan_cell_width); t2*=p_aabb.size[(closest_axis+2)%3]/float(color_scan_cell_width); Color albedo_accum; Color emission_accum; Vector3 normal_accum; float alpha=0.0; //map to a grid average in the best axis for this face for(int i=0;i<color_scan_cell_width;i++) { Vector3 ofs_i=float(i)*t1; for(int j=0;j<color_scan_cell_width;j++) { Vector3 ofs_j=float(j)*t2; Vector3 from = p_aabb.pos+ofs_i+ofs_j; Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis]; Vector3 half = (to-from)*0.5; //is in this cell? if (!fast_tri_box_overlap(from+half,half,p_vtx)) { continue; //face does not span this cell } //go from -size to +size*2 to avoid skipping collisions Vector3 ray_from = from + (t1+t2)*0.5 - axis * p_aabb.size[closest_axis]; Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis]*2; Vector3 intersection; if (!Geometry::ray_intersects_triangle(ray_from,ray_to,p_vtx[0],p_vtx[1],p_vtx[2],&intersection)) { //no intersect? look in edges float closest_dist=1e20; for(int j=0;j<3;j++) { Vector3 c; Vector3 inters; Geometry::get_closest_points_between_segments(p_vtx[j],p_vtx[(j+1)%3],ray_from,ray_to,inters,c); float d=c.distance_to(intersection); if (j==0 || d<closest_dist) { closest_dist=d; intersection=inters; } } } Vector2 uv = get_uv(intersection,p_vtx,p_uv); int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1); int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1); int ofs = uv_y*bake_texture_size+uv_x; albedo_accum.r+=p_material.albedo[ofs].r; albedo_accum.g+=p_material.albedo[ofs].g; albedo_accum.b+=p_material.albedo[ofs].b; albedo_accum.a+=p_material.albedo[ofs].a; emission_accum.r+=p_material.emission[ofs].r; emission_accum.g+=p_material.emission[ofs].g; emission_accum.b+=p_material.emission[ofs].b; normal_accum+=normal; alpha+=1.0; } } if (alpha==0) { //could not in any way get texture information.. so use closest point to center Face3 f( p_vtx[0],p_vtx[1],p_vtx[2]); Vector3 inters = f.get_closest_point_to(p_aabb.pos+p_aabb.size*0.5); Vector2 uv = get_uv(inters,p_vtx,p_uv); int uv_x = CLAMP(Math::fposmod(uv.x,1.0)*bake_texture_size,0,bake_texture_size-1); int uv_y = CLAMP(Math::fposmod(uv.y,1.0)*bake_texture_size,0,bake_texture_size-1); int ofs = uv_y*bake_texture_size+uv_x; alpha = 1.0/(color_scan_cell_width*color_scan_cell_width); albedo_accum.r=p_material.albedo[ofs].r*alpha; albedo_accum.g=p_material.albedo[ofs].g*alpha; albedo_accum.b=p_material.albedo[ofs].b*alpha; albedo_accum.a=p_material.albedo[ofs].a*alpha; emission_accum.r=p_material.emission[ofs].r*alpha; emission_accum.g=p_material.emission[ofs].g*alpha; emission_accum.b=p_material.emission[ofs].b*alpha; normal_accum*=alpha; } else { float accdiv = 1.0/(color_scan_cell_width*color_scan_cell_width); alpha*=accdiv; albedo_accum.r*=accdiv; albedo_accum.g*=accdiv; albedo_accum.b*=accdiv; albedo_accum.a*=accdiv; emission_accum.r*=accdiv; emission_accum.g*=accdiv; emission_accum.b*=accdiv; normal_accum*=accdiv; } //put this temporarily here, corrected in a later step p_baker->bake_cells[p_idx].albedo[0]+=albedo_accum.r; p_baker->bake_cells[p_idx].albedo[1]+=albedo_accum.g; p_baker->bake_cells[p_idx].albedo[2]+=albedo_accum.b; p_baker->bake_cells[p_idx].emission[0]+=emission_accum.r; p_baker->bake_cells[p_idx].emission[1]+=emission_accum.g; p_baker->bake_cells[p_idx].emission[2]+=emission_accum.b; p_baker->bake_cells[p_idx].normal[0]+=normal_accum.x; p_baker->bake_cells[p_idx].normal[1]+=normal_accum.y; p_baker->bake_cells[p_idx].normal[2]+=normal_accum.z; p_baker->bake_cells[p_idx].alpha+=alpha; static const Vector3 side_normals[6]={ Vector3(-1, 0, 0), Vector3( 1, 0, 0), Vector3( 0,-1, 0), Vector3( 0, 1, 0), Vector3( 0, 0,-1), Vector3( 0, 0, 1), }; /* for(int i=0;i<6;i++) { if (normal.dot(side_normals[i])>CMP_EPSILON) { p_baker->bake_cells[p_idx].used_sides|=(1<<i); } }*/ } else { //go down int half = (1<<(p_baker->cell_subdiv-1)) >> (p_level+1); for(int i=0;i<8;i++) { Rect3 aabb=p_aabb; aabb.size*=0.5; int nx=p_x; int ny=p_y; int nz=p_z; if (i&1) { aabb.pos.x+=aabb.size.x; nx+=half; } if (i&2) { aabb.pos.y+=aabb.size.y; ny+=half; } if (i&4) { aabb.pos.z+=aabb.size.z; nz+=half; } //make sure to not plot beyond limits if (nx<0 || nx>=p_baker->axis_cell_size[0] || ny<0 || ny>=p_baker->axis_cell_size[1] || nz<0 || nz>=p_baker->axis_cell_size[2]) continue; { Rect3 test_aabb=aabb; //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time Vector3 qsize = test_aabb.size*0.5; //quarter size, for fast aabb test if (!fast_tri_box_overlap(test_aabb.pos+qsize,qsize,p_vtx)) { //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { //does not fit in child, go on continue; } } if (p_baker->bake_cells[p_idx].childs[i]==Baker::CHILD_EMPTY) { //sub cell must be created uint32_t child_idx = p_baker->bake_cells.size(); p_baker->bake_cells[p_idx].childs[i]=child_idx; p_baker->bake_cells.resize( p_baker->bake_cells.size() + 1); p_baker->bake_cells[child_idx].level=p_level+1; } _plot_face(p_baker->bake_cells[p_idx].childs[i],p_level+1,nx,ny,nz,p_vtx,p_uv,p_material,aabb,p_baker); } } }
//--------------------------------------------------------------------- void RenderSystem::addClipPlane (Real A, Real B, Real C, Real D) { addClipPlane(Plane(A, B, C, D)); }
// on "init" you need to initialize your instance bool City_layer::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } selected=nullptr; horizontalPlane=Plane(Vec3(0,1,0),Vec3(0,0,0)); _rotation=0.f; //_firstrotation=0.f; Size size=Director::getInstance()->getWinSize(); pCamera=Camera::createPerspective(60.0,size.width/size.height,0.1f,2000); pCamera->setCameraFlag(CameraFlag::USER1); pCamera->setPosition3D(Vec3(0,250,500)); pCamera->lookAt(Vec3(0,0,0)); addChild(pCamera); //sdsdsdsd node1=DrawNode3D::create(); node1->clear(); node1->setCameraMask(2); addChild(node1); // 天空盒 // Skybox*sky=Skybox::create("Default/desert_left.jpg", "Default/desert_right.jpg", "Default/desert_top.jpg", "Default/desert_top.jpg", "Default/desert_front.jpg", "Default/desert_back.jpg"); // sky->setCameraMask(2); // addChild(sky); // Terrain::DetailMap r("TerrainTest/dirt.jpg"),g("TerrainTest/Grass2.jpg"),b("TerrainTest/road.jpg"),a("TerrainTest/GreenSkin.jpg"); // // Terrain::TerrainData data("TerrainTest/heightmap16.jpg","TerrainTest/alphamap.png",r,g,b,a); // // _terrain = Terrain::create(data,Terrain::CrackFixedType::SKIRT); // _terrain->setLODDistance(3.2f,6.4f,9.6f); // _terrain->setMaxDetailMapAmount(4); // addChild(_terrain); // _terrain->setCameraMask(2); // _terrain->setDrawWire(false); Terrain::DetailMap r("TerrainTest/dirt.jpg"),g("TerrainTest/Grass2.jpg"),b("TerrainTest/road.jpg"),a("TerrainTest/GreenSkin.jpg"); //Terrain::TerrainData data("TerrainTest/heightmap0.jpg","TerrainTest/alphamapyellow.png",r,g,b,a); Terrain::TerrainData data("TerrainTest/heightmap16.jpg","TerrainTest/alphamap.png",r,g,b,a); _terrain = Terrain::create(data,Terrain::CrackFixedType::SKIRT); //_terrain->setLightMap("TerrainTest/Lightmap.png"); _terrain->setLODDistance(3.2f,6.4f,9.6f); _terrain->setMaxDetailMapAmount(4); addChild(_terrain); _terrain->setScale(20.f, 1.f); _terrain->setScaleZ(20.f); _terrain->setCameraMask(2); _terrain->setDrawWire(false); // create_house("garbageTruck", Vec3(-50,0,100), Vec3(0,0,0),0.3); create_house("fanceWooden", Vec3(100,0,-100), Vec3(0,0,0),0.3); create_human1(Vec3(-50,0,100),1); create_human2(Vec3(50,0,100),1); create_house("houseBig", Vec3(-100,0,-100), Vec3(0,0,0),0.3); // auto floor=Sprite3D::create("plane.c3t","plane.png"); // floor->setPosition3D(Vec3(480,0,0)); // floor->setScaleX(100); // floor->setScaleY(100); // floor->setRotation3D(Vec3(90,0,0)); // floor->setCameraMask(2); // addChild(floor); // // // Charecter1*player=Charecter1::create(); // player->setPosition3D(Vec3(480,10,0)); // player->setRotation3D(Vec3(0,0,0)); // player->stand(); // player->setCameraMask(2); // addChild(player,0,9); // // create_monster(Vec3(300,10,200)); // create_monster(Vec3(500,10,-100)); // create_monster(Vec3(-100,10,-400)); // create_monster(Vec3(-100,10,300)); // create_monster(Vec3(-900,10,1300)); // create_monster(Vec3(-900,10,-1300)); // create_monster(Vec3(1500,10,1300)); // create_monster(Vec3(1500,10,-1300)); auto touchEvt=EventListenerTouchOneByOne::create(); touchEvt->onTouchBegan=[=](Touch*ptouch,Event*pevent){ auto location = ptouch->getLocationInView(); auto obbSize = vecObj.size(); if(obbSize) { CCLOG("size:%lu",obbSize); Ray ray; calculateRayByLocationInView(&ray,location); bool touchOne=false; for(decltype(obbSize) i = 0; i < obbSize; i++) { // Vec3 des = ray.intersects(horizontalPlane); // CCLOG("X:%f,Y:%f,Z:%f",des.x,des.y,des.z); // CCLOG("i:%lu",i); if(ray.intersects(vecObj.at(i)->getAABB())) { touchOne=true; if(dynamic_cast<CharecterBase*>(selected)){ auto pp = static_cast<CharecterBase*>(selected); pp->mainLogic(); pp->scheduleUpdate(); } selected=vecObj.at(i); // Vec3 corners[8]={}; // AABB aabbsp1=_aabb[i]; // aabbsp1.getCorners(corners); // node1->drawCube(corners, Color4F(1,0,0,1)); } } if(!touchOne){ if(selected){ auto location = ptouch->getLocationInView(); Ray ray; calculateRayByLocationInView(&ray,location); Vec3 des = ray.intersects(horizontalPlane); if(dynamic_cast<CharecterBase*>(selected)){ //旋转 selected->unscheduleAllCallbacks(); Vec3 delta=des-selected->getPosition3D(); float angle = Vec2(0,1).getAngle(Vec2(delta.x,delta.z)); if(delta.x!=0||delta.z!=0){ Quaternion tt(Vec3(0,-1,0),angle); selected->setRotationQuat(tt); } //移动 auto pp = static_cast<CharecterBase*>(selected); pp->speedDirection=Vec3(0,0,0);//自由移动失效 pp->walk(); auto time =delta.length()/pp->walk_speed/30; CCLOG("%f->length,%f->time",delta.length(),time); pp->runAction(Sequence::create(MoveTo::create(time, des),CallFuncN::create([=](Ref*pSender){ pp->stand(); }),NULL)); }else{ selected=nullptr; } } } } return true; }; touchEvt->onTouchMoved=[=](Touch*ptouch,Event*pevent){ // 圆面相机 第3人称相机的移动 // auto location=ptouch->getLocation(); // Vec2 newPos=ptouch->getPreviousLocation()-location; // _rotation+=newPos.x/1000; //算出角度 // // float deltax=100*sin(_rotation);//x增量 // float deltaz=100*cos(_rotation);//z增量 // pCamera->setPosition3D(Vec3(deltax,50,deltaz)); // pCamera->lookAt(Vec3(0,0,0)); auto location = ptouch->getLocation(); auto delta=ptouch->getDelta(); pCamera->setPosition3D(pCamera->getPosition3D()+Vec3(-delta.x,0,delta.y)); // pCamera->lookAt(Vec3(0,0,0)); }; // touchEvt->onTouchEnded=[=](Touch*ptouch,Event*pevent){ // if(selected){ // auto location = ptouch->getLocationInView(); // Ray ray; // calculateRayByLocationInView(&ray,location); // Vec3 des = ray.intersects(horizontalPlane); // // if(dynamic_cast<CharecterBase*>(selected)){ // //旋转 // selected->unscheduleAllCallbacks(); // // Vec3 delta=des-selected->getPosition3D(); // // float angle = Vec2(0,1).getAngle(Vec2(delta.x,delta.z)); // if(delta.x!=0||delta.z!=0){ // Quaternion tt(Vec3(0,-1,0),angle); // selected->setRotationQuat(tt); // } // //移动 // auto pp = static_cast<CharecterBase*>(selected); // pp->speedDirection=Vec3(0,0,0);//自由移动失效 // pp->walk(); // // auto time =delta.length()/pp->walk_speed/30; // // CCLOG("%f->length,%f->time",delta.length(),time); // pp->runAction(Sequence::create(MoveTo::create(time, des),CallFuncN::create([=](Ref*pSender){ // pp->stand(); // }),NULL)); // // }else{ // selected=nullptr; // } // // } // }; Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchEvt,this); // scheduleUpdate(); //地图缩放 auto listener=EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan=[&](const std::vector<Touch*>&touches,Event *pevent) { Director*director=Director::getInstance(); if (touches.size()>=2) { auto point1=director->convertToGL(touches.at(0)->getLocation()); auto point2=director->convertToGL(touches.at(1)->getLocation()); _distance=point1.getDistance(point2); } }; listener->onTouchesMoved=[&](const std::vector<Touch*>&touches,Event *pevent) { Director*director=Director::getInstance(); if (touches.size()>=2) { auto point1=director->convertToGL(touches.at(0)->getLocation()); auto point2=director->convertToGL(touches.at(1)->getLocation()); float new_distance=point1.getDistance(point2); float delta=new_distance-_distance; pCamera->setPosition3D(pCamera->getPosition3D()+Vec3(0,delta,delta)); _distance=new_distance; } }; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); return true; }
void Camera::SetReflectionPlaneAttr(const Vector4& value) { SetReflectionPlane(Plane(value)); }
Variant::operator String() const { switch( type ) { case NIL: return ""; case BOOL: return _data._bool ? "True" : "False"; case INT: return String::num(_data._int); case REAL: return String::num(_data._real); case STRING: return *reinterpret_cast<const String*>(_data._mem); case VECTOR2: return operator Vector2(); case RECT2: return operator Rect2(); case MATRIX32: return operator Matrix32(); case VECTOR3: return operator Vector3(); case PLANE: return operator Plane(); //case QUAT: case _AABB: return operator AABB(); case QUAT: return operator Quat(); case MATRIX3: return operator Matrix3(); case TRANSFORM: return operator Transform(); case NODE_PATH: return operator NodePath(); case INPUT_EVENT: return operator InputEvent(); case COLOR: return String::num( operator Color().r)+","+String::num( operator Color().g)+","+String::num( operator Color().b)+","+String::num( operator Color().a) ; case DICTIONARY: { const Dictionary &d =*reinterpret_cast<const Dictionary*>(_data._mem); //const String *K=NULL; String str; List<Variant> keys; d.get_key_list(&keys); Vector<_VariantStrPair> pairs; for(List<Variant>::Element *E=keys.front();E;E=E->next()) { _VariantStrPair sp; sp.key=String(E->get()); sp.value=d[E->get()]; pairs.push_back(sp); } pairs.sort(); for(int i=0;i<pairs.size();i++) { if (i>0) str+=", "; str+="("+pairs[i].key+":"+pairs[i].value+")"; } return str; } break; case VECTOR3_ARRAY: { DVector<Vector3> vec = operator DVector<Vector3>(); String str; for(int i=0;i<vec.size();i++) { if (i>0) str+=", "; str=str+Variant( vec[i] ); } return str; } break; case STRING_ARRAY: { DVector<String> vec = operator DVector<String>(); String str; for(int i=0;i<vec.size();i++) { if (i>0) str+=", "; str=str+vec[i]; } return str; } break; case INT_ARRAY: { DVector<int> vec = operator DVector<int>(); String str; for(int i=0;i<vec.size();i++) { if (i>0) str+=", "; str=str+itos(vec[i]); } return str; } break; case REAL_ARRAY: { DVector<real_t> vec = operator DVector<real_t>(); String str; for(int i=0;i<vec.size();i++) { if (i>0) str+=", "; str=str+rtos(vec[i]); } return str; } break; case ARRAY: { Array arr = operator Array(); String str; for (int i=0; i<arr.size(); i++) { if (i) str+=", "; str += String(arr[i]); }; return str; } break; case OBJECT: { if (_get_obj().obj) return "["+_get_obj().obj->get_type()+":"+itos(_get_obj().obj->get_instance_ID())+"]"; else return "[Object:null]"; } break; default: { return "["+get_type_name(type)+"]"; } } return ""; }
void Camera::SetClipPlaneAttr(const Vector4& value) { SetClipPlane(Plane(value)); }
bool Variant::is_zero() const { switch( type ) { case NIL: { return true; } break; // atomic types case BOOL: { return _data._bool==false; } break; case INT: { return _data._int==0; } break; case REAL: { return _data._real==0; } break; case STRING: { return *reinterpret_cast<const String*>(_data._mem)==String(); } break; // math types case VECTOR2: { return *reinterpret_cast<const Vector2*>(_data._mem)==Vector2(); } break; case RECT2: { return *reinterpret_cast<const Rect2*>(_data._mem)==Rect2(); } break; case MATRIX32: { return *_data._matrix32==Matrix32(); } break; case VECTOR3: { return *reinterpret_cast<const Vector3*>(_data._mem)==Vector3(); } break; case PLANE: { return *reinterpret_cast<const Plane*>(_data._mem)==Plane(); } break; /* case QUAT: { } break;*/ case _AABB: { return *_data._aabb==AABB(); } break; case QUAT: { *reinterpret_cast<const Quat*>(_data._mem)==Quat(); } break; case MATRIX3: { return *_data._matrix3==Matrix3(); } break; case TRANSFORM: { return *_data._transform == Transform(); } break; // misc types case COLOR: { return *reinterpret_cast<const Color*>(_data._mem)==Color(); } break; case IMAGE: { return _data._image->empty(); } break; case _RID: { return *reinterpret_cast<const RID*>(_data._mem)==RID(); } break; case OBJECT: { return _get_obj().obj==NULL; } break; case NODE_PATH: { return reinterpret_cast<const NodePath*>(_data._mem)->is_empty(); } break; case INPUT_EVENT: { return _data._input_event->type==InputEvent::NONE; } break; case DICTIONARY: { return reinterpret_cast<const Dictionary*>(_data._mem)->empty(); } break; case ARRAY: { return reinterpret_cast<const Array*>(_data._mem)->empty(); } break; // arrays case RAW_ARRAY: { return reinterpret_cast<const DVector<uint8_t>*>(_data._mem)->size()==0; } break; case INT_ARRAY: { return reinterpret_cast<const DVector<int>*>(_data._mem)->size()==0; } break; case REAL_ARRAY: { return reinterpret_cast<const DVector<real_t>*>(_data._mem)->size()==0; } break; case STRING_ARRAY: { return reinterpret_cast<const DVector<String>*>(_data._mem)->size()==0; } break; case VECTOR2_ARRAY: { return reinterpret_cast<const DVector<Vector2>*>(_data._mem)->size()==0; } break; case VECTOR3_ARRAY: { return reinterpret_cast<const DVector<Vector3>*>(_data._mem)->size()==0; } break; case COLOR_ARRAY: { return reinterpret_cast<const DVector<Color>*>(_data._mem)->size()==0; } break; default: {} } return false; }
void CuboidCollisionShape::GetIncidentReferencePolygon(const PhysicsObject* currentObject, const Vector3& axis, std::list<Vector3>* out_face, Vector3* out_normal, std::vector<Plane>* out_adjacent_planes) const { Matrix4 wsTransform = currentObject->GetWorldSpaceTransform() * Matrix4::Scale(m_CuboidHalfDimensions); Matrix3 invNormalMatrix = Matrix3::Inverse(Matrix3(wsTransform)); Matrix3 normalMatrix = Matrix3::Transpose(invNormalMatrix); Vector3 local_axis = invNormalMatrix * axis; int minVertex, maxVertex; m_CubeHull.GetMinMaxVerticesInAxis(local_axis, &minVertex, &maxVertex); const HullVertex& vert = m_CubeHull.GetVertex(maxVertex); const HullFace* best_face = 0; float best_correlation = -FLT_MAX; for (int faceIdx : vert.enclosing_faces) { const HullFace* face = &m_CubeHull.GetFace(faceIdx); float temp_correlation = Vector3::Dot(local_axis, face->normal); if (temp_correlation > best_correlation) { best_correlation = temp_correlation; best_face = face; } } if (out_normal) { *out_normal = normalMatrix * best_face->normal; (*out_normal).Normalise(); } if (out_face) { for (int vertIdx : best_face->vert_ids) { const HullVertex& vert = m_CubeHull.GetVertex(vertIdx); out_face->push_back(wsTransform * vert.pos); } } if (out_adjacent_planes) { //Add the reference face itself to the list of adjacent planes Vector3 wsPointOnPlane = wsTransform * m_CubeHull.GetVertex(m_CubeHull.GetEdge(best_face->edge_ids[0]).vStart).pos; Vector3 planeNrml = -(normalMatrix * best_face->normal); planeNrml.Normalise(); float planeDist = -Vector3::Dot(planeNrml, wsPointOnPlane); out_adjacent_planes->push_back(Plane(planeNrml, planeDist)); for (int edgeIdx : best_face->edge_ids) { const HullEdge& edge = m_CubeHull.GetEdge(edgeIdx); wsPointOnPlane = wsTransform * m_CubeHull.GetVertex(edge.vStart).pos; for (int adjFaceIdx : edge.enclosing_faces) { if (adjFaceIdx != best_face->idx) { const HullFace& adjFace = m_CubeHull.GetFace(adjFaceIdx); planeNrml = -(normalMatrix * adjFace.normal); planeNrml.Normalise(); planeDist = -Vector3::Dot(planeNrml, wsPointOnPlane); out_adjacent_planes->push_back(Plane(planeNrml, planeDist)); } } } } }
//=======================================================================// void stitch::BeamTree::build(const size_t chunkSize, const uint8_t splitAxis) {//Only makes use of cone origins to build tree. It is assumed that cones that originate next to each other points in similar directions! //New potential child trees. BeamTree *tree0=new BeamTree; BeamTree *tree1=new BeamTree; //Build the beamTree based on the end-cap centres instead of the generator centres. //=== Find centre of beam end-cap OR BV === Vec3 centre;//Set to zero. if (beamSegmentVector_.size()>0) { std::vector<stitch::BeamSegment *>::const_iterator constBeamSegmentIter=beamSegmentVector_.begin(); for (; constBeamSegmentIter!=beamSegmentVector_.end(); ++constBeamSegmentIter) {//Do a linear traversal through the beam segments. (*constBeamSegmentIter)->updateBV(); if ((*constBeamSegmentIter)->hasEndCap_) { centre+=(*constBeamSegmentIter)->endCapVertices_[0]; } else { centre+=(*constBeamSegmentIter)->getBVBrush().centre_; } } centre/=beamSegmentVector_.size(); } //================================ Plane binarySpacePartition(Vec3(0.0f, 0.0f, 0.0f), 0.0f); if (splitAxis==0) { binarySpacePartition=Plane(Vec3(1.0f, 0.0f, 0.0f), centre.x());//right-hand space. } else if (splitAxis==1) { binarySpacePartition=Plane(Vec3(0.0f, 1.0f, 0.0f), centre.y());//right-hand space. } else if (splitAxis==2) { binarySpacePartition=Plane(Vec3(0.0f, 0.0f, 1.0f), centre.z());//right-hand space. } //=== Split beam segments into two brances according to their beam orig and the binary space partition plane. { std::vector<BeamSegment *>::const_iterator beamSegmentIter=beamSegmentVector_.begin(); for (; beamSegmentIter!=beamSegmentVector_.end(); ++beamSegmentIter) { BeamSegment *beamSegment=(*beamSegmentIter); stitch::Vec3 refVert; if (beamSegment->hasEndCap_) { refVert=beamSegment->endCapVertices_[0]; } else { refVert=beamSegment->getBVBrush().centre_; } if (refVert*binarySpacePartition.normal_ < binarySpacePartition.d_) {//Object is in space of tree0. tree0->addBeamSegment(beamSegment); } else {//Object is in space of tree1. tree1->addBeamSegment(beamSegment); } } //beamSegmentVector_.clear();//Does not delete the beam segments pointed to by the vector entries. std::vector<stitch::BeamSegment *>().swap(beamSegmentVector_);//swap with new empty vector. } //=== //=== Add child trees to this parent and build the child hierarchy === { if (tree0->beamSegmentVector_.size()>0) { beamTreeVector_.push_back(tree0);//Add child tree. There can be more than two child trees if the build mehod is called multiple times. } if (tree0->beamSegmentVector_.size()>chunkSize) { tree0->build(chunkSize, (splitAxis+1)%3);//Recursively build the tree. } if (tree1->beamSegmentVector_.size()>0) { beamTreeVector_.push_back(tree1);//Add child tree. There can be more than two child trees if the build mehod is called multiple times. } if (tree1->beamSegmentVector_.size()>chunkSize) { tree1->build(chunkSize, (splitAxis+1)%3);//Recursively build the tree. } } //==================================================================== }
void PlaneReflection::setHeight (float height) { mWaterPlane = Plane(Ogre::Vector3(0,0,1), height); mErrorPlane = Plane(Ogre::Vector3(0,0,1), height - 5); mErrorPlaneUnderwater = Plane(Ogre::Vector3(0,0,-1), -height - 5); }
Vector<Plane> CameraMatrix::get_projection_planes(const Transform& p_transform) const { /** Fast Plane Extraction from combined modelview/projection matrices. * References: * http://www.markmorley.com/opengl/frustumculling.html * http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf */ Vector<Plane> planes; const float * matrix = (const float*)this->matrix; Plane new_plane; ///////--- Near Plane ---/////// new_plane=Plane(matrix[ 3] + matrix[ 2], matrix[ 7] + matrix[ 6], matrix[11] + matrix[10], matrix[15] + matrix[14]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); ///////--- Far Plane ---/////// new_plane=Plane(matrix[ 3] - matrix[ 2], matrix[ 7] - matrix[ 6], matrix[11] - matrix[10], matrix[15] - matrix[14]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); ///////--- Left Plane ---/////// new_plane=Plane(matrix[ 3] + matrix[ 0], matrix[ 7] + matrix[ 4], matrix[11] + matrix[ 8], matrix[15] + matrix[12]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); ///////--- Top Plane ---/////// new_plane=Plane(matrix[ 3] - matrix[ 1], matrix[ 7] - matrix[ 5], matrix[11] - matrix[ 9], matrix[15] - matrix[13]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); ///////--- Right Plane ---/////// new_plane=Plane(matrix[ 3] - matrix[ 0], matrix[ 7] - matrix[ 4], matrix[11] - matrix[ 8], matrix[15] - matrix[12]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); ///////--- Bottom Plane ---/////// new_plane=Plane(matrix[ 3] + matrix[ 1], matrix[ 7] + matrix[ 5], matrix[11] + matrix[ 9], matrix[15] + matrix[13]); new_plane.normal=-new_plane.normal; new_plane.normalize(); planes.push_back( p_transform.xform(new_plane) ); return planes; }
Water::Water (Ogre::Camera *camera, RenderingManager* rend) : mCamera (camera), mSceneMgr (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mActive(1), mToggled(1), mRendering(rend), mWaterTimer(0.f), mReflection(NULL), mRefraction(NULL), mSimulation(NULL), mPlayer(0,0) { mSimulation = new RippleSimulation(mSceneMgr); mSky = rend->getSkyManager(); mMaterial = MaterialManager::getSingleton().getByName("Water"); mTop = 0; mIsUnderwater = false; mWaterPlane = Plane(Vector3::UNIT_Z, 0); MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,3, Vector3::UNIT_Y); mWater = mSceneMgr->createEntity("water"); mWater->setVisibilityFlags(RV_Water); mWater->setCastShadows(false); mWater->setRenderQueueGroup(RQG_Alpha); mWaterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mWaterNode->attachObject(mWater); applyRTT(); applyVisibilityMask(); mWater->setMaterial(mMaterial); setHeight(mTop); sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water"); m->setListener (this); // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- // ---------------------------------------------------------------------------------------------- /* if (Settings::Manager::getBool("shader", "Water")) { OverlayManager& mgr = OverlayManager::getSingleton(); Overlay* overlay; // destroy if already exists if ((overlay = mgr.getByName("ReflectionDebugOverlay"))) mgr.destroy(overlay); overlay = mgr.create("ReflectionDebugOverlay"); if (MaterialManager::getSingleton().resourceExists("Ogre/ReflectionDebugTexture")) MaterialManager::getSingleton().remove("Ogre/ReflectionDebugTexture"); MaterialPtr debugMat = MaterialManager::getSingleton().create( "Ogre/ReflectionDebugTexture", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(mReflectionTexture->getName()); OverlayContainer* debugPanel; // destroy container if exists try { if ((debugPanel = static_cast<OverlayContainer*>( mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel" )))) mgr.destroyOverlayElement(debugPanel); } catch (Ogre::Exception&) {} debugPanel = (OverlayContainer*) (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/ReflectionDebugTexPanel")); debugPanel->_setPosition(0, 0.55); debugPanel->_setDimensions(0.3, 0.3); debugPanel->setMaterialName(debugMat->getName()); debugPanel->show(); overlay->add2D(debugPanel); overlay->show(); } */ }
// The resulting hull will not contain interior points // Note that this is a cheap and cheerful implementation that can only handle // reasonably small point sets. However, except for the final hull it doesn't do any dynamic // memory allocation - all the work happens on the stack. Hull* Hull::MakeHull(int numPoints, const Point3* pPoints) { assert(numPoints >= 4); assert(pPoints); // check first 4 points are disjoint // TODO: make it search points so it can cope better with this assert(Length(pPoints[1] - pPoints[0]) > 0.01f); assert(Length(pPoints[2] - pPoints[0]) > 0.01f); assert(Length(pPoints[3] - pPoints[0]) > 0.01f); assert(Length(pPoints[2] - pPoints[1]) > 0.01f); assert(Length(pPoints[3] - pPoints[1]) > 0.01f); assert(Length(pPoints[3] - pPoints[2]) > 0.01f); s_pPoints = pPoints; // put all temp faces on a free list TmpFace tmpFaces[kMaxFaces]; s_firstFreeTmpFace = 0; s_firstUsedTmpFace = -1; s_pTmpFaces = tmpFaces; for (short i = 0; i < kMaxEdges; i++) { tmpFaces[i].m_index = i; tmpFaces[i].m_next = i + 1; } tmpFaces[kMaxFaces - 1].m_next = -1; // put all temp edges on a free list TmpEdge tmpEdges[kMaxEdges]; s_firstFreeTmpEdge = 0; s_firstUsedTmpEdge = -1; s_pTmpEdges = tmpEdges; for (short i = 0; i < kMaxEdges; i++) { tmpEdges[i].m_index = i; tmpEdges[i].m_next = i + 1; } tmpEdges[kMaxEdges - 1].m_next = -1; // make initial tetrahedron Plane plane = Plane(pPoints[0], pPoints[1], pPoints[2]); Scalar dot = Dot(plane, pPoints[3]); assert(Abs(dot) > 0.01f); // first 4 points are co-planar if (IsNegative(dot)) { AddTmpFace(0, 1, 2); AddTmpFace(1, 0, 3); AddTmpFace(0, 2, 3); AddTmpFace(2, 1, 3); } else { AddTmpFace(2, 1, (short)0); AddTmpFace(1, 2, 3); AddTmpFace(2, 0, 3); AddTmpFace(0, 1, 3); } // merge all remaining points for (int i = 4; i < numPoints; i++) if (RemoveVisibleFaces(pPoints[i]) > 0) FillHole(i); return MakeHullFromTemp(); }
void PlayState::update(Real delta) { // fps cam update Vector3 moveVect = mCam->mCamera->getAbsoluteDirection()*7*delta* (mInput->isKeyDown("KC_W")-mInput->isKeyDown("KC_S")) +mCam->mCamera->getAbsoluteRight()*7*delta* (mInput->isKeyDown("KC_D")-mInput->isKeyDown("KC_A")); Real len = moveVect.normalize(); // hacky raycast for portals RaycastReport r = mPhysics->raycast(mCam->getPosition(),moveVect, len,0,COLLISION_GROUP_2);//COLLISION_GROUP_2, COLLISION_GROUP_2); if(!r.hit) { mCam->mPosNode->setPosition(mCam->mPosNode->getPosition() + moveVect * len); } else { // must be a portal Portal* p = static_cast<Portal*>(r.userData); // hacky and not so smooth portal transition if(r.normal.angleBetween(p->mDirection) < 30.f) { Real distTravelled = r.position.distance(mCam->getPosition()); mCam->mPosNode->setPosition(p->mNode->localToWorldPosition( p->mMesh->worldToLocalPosition(mCam->getPosition()))); mCam->mOriNode->setOrientation(p->mNode->localToWorldOrientation( p->mMesh->worldToLocalOrientation(mCam->mOriNode->getOrientation()))); len -= 2*distTravelled; Vector3 newDir = mCam->getDirection(); mCam->mPosNode->setPosition(mCam->mPosNode->getPosition() + newDir * len); //mCam->up1 = p->upv; //mCam->up2 = p->mSibling->upv; //mCam->slerpTime = 1.f; } else { mCam->mPosNode->setPosition(mCam->mPosNode->getPosition() + moveVect * len); } } // update player position with the chunk generator mGen->setPlayerPos(mCam->getPosition()); // same o' same o' if(mInput->wasKeyPressed("KC_ESCAPE")) mEngine->shutdown(); // screenshots if(mInput->wasKeyPressed("KC_P")) mGfx->takeScreenshot(TimeManager::getPtr()->getTimestamp()); // update debug overlay mFpsText->setCaption("FPS: "+ StringUtils::toString(1.f/delta)); mBatchCountText->setCaption("Batches: " + StringUtils::toString(mGfx->getBatchCount())); mActiveChunkCountText->setCaption("Active Chunks: " + StringUtils::toString(mGen->getNumActiveChunks())); mGeneratedChunkCountText->setCaption("Generated Chunks: " + StringUtils::toString(mGen->getNumGeneratedChunks())); if(mInput->wasButtonPressed("MB_Right")) { if(mInput->isKeyDown("KC_L")) { RaycastReport r = mPhysics->raycast(mCam->getPosition(),mCam->getDirection(), 50.f,COLLISION_GROUP_3,COLLISION_GROUP_3); if(r.hit && r.userData) { BasicChunk* bc = static_cast<BasicChunk*>(r.userData); ChunkCoords cc = getBlockFromRaycast(r.position, r.normal, bc, true); for(int i = -1; i <= 1; ++i) for(int j = -1; j <= 1; ++j) for(int k = -1; k <= 1; ++k) { ChunkCoords cc2 = cc + ChunkCoords(i,j,k); BasicChunk* bc2 = correctChunkCoords(bc, cc2); cc2.data = 0; bc2->changeBlock(cc2); } } } else if(!mInput->isKeyDown("KC_LSHIFT")) { RaycastReport r = mPhysics->raycast(mCam->getPosition(),mCam->getDirection(), 8.f,COLLISION_GROUP_3,COLLISION_GROUP_3); if(r.hit && r.userData) { BasicChunk* bc = static_cast<BasicChunk*>(r.userData); ChunkCoords cc = getBlockFromRaycast(r.position, r.normal, bc, true); bc = correctChunkCoords(bc, cc); cc.data = 0; bc->changeBlock(cc); } } else { RaycastReport r = mPhysics->raycast(mCam->getPosition(),mCam->getDirection(), 50.f,COLLISION_GROUP_3,COLLISION_GROUP_3); // YUCK if(r.hit && r.userData) { BasicChunk* bc = static_cast<BasicChunk*>(r.userData); ChunkCoords cc = getBlockFromRaycast(r.position, r.normal, bc, false); bc = correctChunkCoords(bc, cc); BlockDirection d = getBlockDirectionFromVector(r.normal); BlockDirection d_ = getBlockDirectionFromVector(r.normal * -1); BlockDirection up = getBlockDirectionFromVector( Plane(r.normal, 0).projectVector(mCam->mCamera->getAbsoluteUp())); ChunkCoords cc2 = cc << up; BasicChunk* bc2 = correctChunkCoords(bc, cc2); if(!getBlockVal(bc, cc) && !getBlockVal(bc2, cc2) && getBlockVal(bc, cc << d_) && getBlockVal(bc2, cc2 << d_)) { Vector3 adjPos = bc->getPosition() - OFFSET + Vector3(cc.x, cc.y, cc.z); adjPos -= BLOCK_NORMALS[d] * 0.5f; adjPos += BLOCK_NORMALS[up] * 0.5f; for(int i = 0; i < 2; ++i) { if(mPortals[1]->chunks[0]) mPortals[1]->chunks[0]->clearLights(); } mPortals[1]->lightVals[0] = getLightVal(bc, cc); mPortals[1]->lightVals[1] = getLightVal(bc2, cc2); mPortals[1]->cc[0] = cc; mPortals[1]->cc[1] = cc2; mPortals[1]->chunks[0] = bc; if(bc2 != bc) { mPortals[1]->chunks[1] = bc2; } else { mPortals[1]->chunks[1] = 0; } mPortals[1]->placed = true; if(mPortals[0]->placed && mPortals[1]->placed) { for(int i = 0; i < 2; ++i) { if(mPortals[0]->lightVals[i] < mPortals[1]->lightVals[i]) { BasicChunk* tmp = mPortals[0]->chunks[i] ? mPortals[0]->chunks[i] : mPortals[0]->chunks[0]; tmp->addLight(mPortals[0]->cc[i], mPortals[1]->lightVals[i]); } else { BasicChunk* tmp = mPortals[1]->chunks[i] ? mPortals[1]->chunks[i] : mPortals[1]->chunks[0]; tmp->addLight(mPortals[1]->cc[i], mPortals[0]->lightVals[i]); } } } mPortals[1]->setPosition(adjPos); mPortals[1]->setDirection(d, up); } } } } if(mInput->wasButtonPressed("MB_Left")) { if(!mInput->isKeyDown("KC_LSHIFT")) { RaycastReport r = mPhysics->raycast(mCam->getPosition(),mCam->getDirection(), 5.f,COLLISION_GROUP_3,COLLISION_GROUP_3); if(r.hit && r.userData) { BasicChunk* bc = static_cast<BasicChunk*>(r.userData); ChunkCoords cc = getBlockFromRaycast(r.position, r.normal, bc, false); bc = correctChunkCoords(bc, cc); cc.data = mBlockSelected; bc->changeBlock(cc); } } else { RaycastReport r = mPhysics->raycast(mCam->getPosition(),mCam->getDirection(), 50.f,COLLISION_GROUP_3,COLLISION_GROUP_3); // YUCK if(r.hit && r.userData) { BasicChunk* bc = static_cast<BasicChunk*>(r.userData); ChunkCoords cc = getBlockFromRaycast(r.position, r.normal, bc, false); bc = correctChunkCoords(bc, cc); BlockDirection d = getBlockDirectionFromVector(r.normal); BlockDirection d_ = getBlockDirectionFromVector(r.normal * -1); BlockDirection up = getBlockDirectionFromVector( Plane(r.normal, 0).projectVector(mCam->mCamera->getAbsoluteUp())); ChunkCoords cc2 = cc << up; BasicChunk* bc2 = correctChunkCoords(bc, cc2); if(!getBlockVal(bc, cc) && !getBlockVal(bc2, cc2) && getBlockVal(bc, cc << d_) && getBlockVal(bc2, cc2 << d_)) { Vector3 adjPos = bc->getPosition() - OFFSET + Vector3(cc.x, cc.y, cc.z); adjPos -= BLOCK_NORMALS[d] * 0.5f; adjPos += BLOCK_NORMALS[up] * 0.5f; for(int i = 0; i < 2; ++i) { if(mPortals[0]->chunks[0]) mPortals[0]->chunks[0]->clearLights(); } mPortals[0]->lightVals[0] = getLightVal(bc, cc); mPortals[0]->lightVals[1] = getLightVal(bc2, cc2); mPortals[0]->cc[0] = cc; mPortals[0]->cc[1] = cc2; mPortals[0]->chunks[0] = bc; if(bc2 != bc) { mPortals[0]->chunks[1] = bc2; } else { mPortals[0]->chunks[1] = 0; } mPortals[0]->placed = true; if(mPortals[0]->placed && mPortals[1]->placed) { for(int i = 0; i < 2; ++i) { if(mPortals[0]->lightVals[i] < mPortals[1]->lightVals[i]) { BasicChunk* tmp = mPortals[0]->chunks[i] ? mPortals[0]->chunks[i] : mPortals[0]->chunks[0]; tmp->addLight(mPortals[0]->cc[i], mPortals[1]->lightVals[i]); } else { BasicChunk* tmp = mPortals[1]->chunks[i] ? mPortals[1]->chunks[i] : mPortals[1]->chunks[0]; tmp->addLight(mPortals[1]->cc[i], mPortals[0]->lightVals[i]); } } } mPortals[0]->setPosition(adjPos); mPortals[0]->setDirection(d, up); } } } } }