/// <summary> /// Given a ProjectionAxis, return the appropriate Vector3 conversion. /// </summary> /// <param name="axis"></param> /// <returns></returns> internal static Vector3 ProjectionAxisToVector(ProjectionAxis axis) { switch (axis) { case ProjectionAxis.X: return(Vector3.right); case ProjectionAxis.Y: return(Vector3.up); case ProjectionAxis.Z: return(Vector3.forward); case ProjectionAxis.XNegative: return(-Vector3.right); case ProjectionAxis.YNegative: return(-Vector3.up); case ProjectionAxis.ZNegative: return(-Vector3.forward); default: return(Vector3.zero); } }
static Plane GetPlaneFromCameraDirection() { var sceneView = SceneView.lastActiveSceneView; var cameraDirection = sceneView.camera.transform.forward; float pitch = Mathf.Abs(Vector3.Dot(cameraDirection, Vector3.up)); float right = Mathf.Abs(Vector3.Dot(cameraDirection, Vector3.right)); float forward = Mathf.Abs(Vector3.Dot(cameraDirection, Vector3.forward)); ProjectionAxis axis = ProjectionAxis.Y; // Orthographic view, use X or Z if (pitch < .02f) { if (right > forward) { axis = ProjectionAxis.X; } else { axis = ProjectionAxis.Z; } } return(new Plane(Projection.ProjectionAxisToVector(axis), SceneView.lastActiveSceneView.pivot)); }
public pb_UV(pb_UV uvs) { projectionAxis = uvs.projectionAxis; useWorldSpace = uvs.useWorldSpace; flipU = uvs.flipU; flipV = uvs.flipV; swapUV = uvs.swapUV; fill = uvs.fill; scale = uvs.scale; offset = uvs.offset; rotation = uvs.rotation; justify = uvs.justify; }
public Vector3 projectionValue; ///< If projectionAxis is set to Instance, this is the value that will be used to project UV coordinates. #endregion #region INITIALIZATION public pb_UV() { projectionAxis = ProjectionAxis.AUTO; useWorldSpace = false; justify = Justify.None; flipU = false; flipV = false; swapUV = false; fill = Fill.Tile; scale = new Vector2(1f, 1f); offset = new Vector2(0f, 0f); rotation = 0f; }
public static Vector2[] PlanarProject(Vector3[] verts, Vector3 planeNormal, ProjectionAxis projectionAxis) { Vector2[] uvs = new Vector2[verts.Length]; Vector3 vec = Vector3.zero; switch (projectionAxis) { case ProjectionAxis.X: case ProjectionAxis.X_Negative: vec = Vector3.up; break; case ProjectionAxis.Y: case ProjectionAxis.Y_Negative: vec = Vector3.forward; break; // vec = -Vector3.forward; // break; case ProjectionAxis.Z: case ProjectionAxis.Z_Negative: vec = Vector3.up; break; } /** * Assign vertices to UV coordinates */ Vector3 uAxis, vAxis; // get U axis uAxis = Vector3.Cross(planeNormal, vec); uAxis.Normalize(); // calculate V axis relative to U vAxis = Vector3.Cross(uAxis, planeNormal); vAxis.Normalize(); for (int i = 0; i < verts.Length; i++) { float u, v; u = Vector3.Dot(uAxis, verts[i]); v = Vector3.Dot(vAxis, verts[i]); uvs[i] = new Vector2(u, v); } return(uvs); }
/// <summary> /// Projects UVs for each face using the closest normal on a box and then place the lower left coordinate at the anchor position. /// </summary> /// <param name="mesh"></param> /// <param name="faces"></param> /// <param name="lowerLeftAnchor"></param> /// <param name="channel"></param> public static void ProjectFacesBox(ProBuilderMesh mesh, Face[] faces, Vector2 lowerLeftAnchor, int channel = 0) { Vector2[] uv = GetUVs(mesh, channel); Dictionary <ProjectionAxis, List <Face> > sorted = new Dictionary <ProjectionAxis, List <Face> >(); for (int i = 0; i < faces.Length; i++) { Vector3 nrm = Math.Normal(mesh, faces[i]); ProjectionAxis axis = Projection.VectorToProjectionAxis(nrm); if (sorted.ContainsKey(axis)) { sorted[axis].Add(faces[i]); } else { sorted.Add(axis, new List <Face>() { faces[i] }); } // clean up UV stuff - no shared UV indexes and remove element group faces[i].elementGroup = -1; faces[i].manualUV = true; } foreach (KeyValuePair <ProjectionAxis, List <Face> > kvp in sorted) { int[] distinct = kvp.Value.SelectMany(x => x.distinctIndexesInternal).ToArray(); Vector2[] uvs = Projection.PlanarProject(mesh.positionsInternal, distinct, Projection.ProjectionAxisToVector(kvp.Key)); Vector2 minimalUV = FindMinimalUV(uvs); for (int n = 0; n < distinct.Length; n++) { uv[distinct[n]] = uvs[n] - minimalUV; } SplitUVs(mesh, distinct); } /* and set the msh uv array using the new coordintaes */ ApplyUVs(mesh, uv, channel); }
/** * Projects UVs for each face using the closest normal on a box. */ public static void ProjectFacesBox(pb_Object pb, pb_Face[] faces) { Vector2[] uv = pb.uv; Dictionary <ProjectionAxis, List <pb_Face> > sorted = new Dictionary <ProjectionAxis, List <pb_Face> >(); for (int i = 0; i < faces.Length; i++) { Vector3 nrm = pb_Math.Normal(pb, faces[i]); ProjectionAxis axis = pb_Math.VectorToProjectionAxis(nrm); if (sorted.ContainsKey(axis)) { sorted[axis].Add(faces[i]); } else { sorted.Add(axis, new List <pb_Face>() { faces[i] }); } // clean up UV stuff - no shared UV indices and remove element group faces[i].elementGroup = -1; } foreach (KeyValuePair <ProjectionAxis, List <pb_Face> > kvp in sorted) { int[] distinct = pb_Face.AllTrianglesDistinct(kvp.Value.ToArray()); Vector2[] uvs = pb_Math.PlanarProject(pb.GetVertices(distinct), pb_Math.ProjectionAxisToVector(kvp.Key), kvp.Key); for (int n = 0; n < distinct.Length; n++) { uv[distinct[n]] = uvs[n]; } SplitUVs(pb, distinct); } /* and set the msh uv array using the new coordintaes */ pb.SetUV(uv); pb.ToMesh(); pb.Refresh(); }
internal static Vector3 GetTangentToAxis(ProjectionAxis axis) { // old probuilder didn't respect project axis settings properly, and changing it to the correct version // (ProjectionAxisToVector) would break existing models. switch (axis) { case ProjectionAxis.X: case ProjectionAxis.XNegative: return(Vector3.up); case ProjectionAxis.Y: case ProjectionAxis.YNegative: return(Vector3.forward); case ProjectionAxis.Z: case ProjectionAxis.ZNegative: return(Vector3.up); default: return(Vector3.up); } }
public pb_UV( ProjectionAxis _projectionAxis, bool _useWorldSpace, bool _flipU, bool _flipV, bool _swapUV, Fill _fill, Vector2 _scale, Vector2 _offset, float _rotation, Justify _justify ) { projectionAxis = _projectionAxis; useWorldSpace = _useWorldSpace; flipU = _flipU; flipV = _flipV; swapUV = _swapUV; fill = _fill; scale = _scale; offset = _offset; rotation = _rotation; justify = _justify; }
public HeightMapNoiseModule(string height_map_filename, OpenTK.Vector3 axial_frequencies, OpenTK.Vector3 projection_offset, ProjectionAxis axis) : base(axial_frequencies) { m_heightmap_data = new HeightMapData("Assets\\Textures\\DeformationHeightMaps\\" + height_map_filename); m_projection_axis = axis; m_projection_offset = projection_offset; }
// No default/parameterless constructor, since you need to specify a filename and projection axis. // We assume for the moment that all heightmaps must be located at Assets/Textures/DeformationHeightMaps. // If that restriction becomes a problem, we can change this behavior to either search the entire Assets tree, // or require the higher-level code to provide a full relative path instead of just a filename. // // The projection axis takes the place of the anti_y/pos_y/neg_y params in the base noise module class, so those base // params are not used for this module. public HeightMapNoiseModule(string height_map_filename, ProjectionAxis axis) : base() { m_heightmap_data = new HeightMapData("Assets\\Textures\\DeformationHeightMaps\\" + height_map_filename); m_projection_axis = axis; m_projection_offset = OpenTK.Vector3.Zero; }