How to write a Three-view drawings shader(in Unity3d)? - unity3d

I attempt implement a Three-view drawings shader for simple geometry and have test with this shader,simple as:
float doCos = dot(viewDirection, normalDirection);
float4 texColor;
//2. need board
bool isBackSide = doCos < 0;
if(isBackSide) {
//_Dotted is a 2d texture the board is black dot line
texColor = tex2D(_Dotted, i.tex.xy * _Dotted_ST.xy + _Dotted_ST.zw);
} else {
//_Dotted is a 2d texture the board is black entity line
texColor = tex2D(_Entity, i.tex.xy * _Entity_ST.xy + _Entity_ST.zw);
}
//ignore some color
if(texColor.x > 0.5f) {
discard;
}
return texColor;
There have a problem the dotted line will obvious then entity line when forward plane become steep.also, I add a rim line but its not point so I ignore it.
in order to clarify, I use two questions:
1. how to modify that shader solve dotted line problem?
2. Does have exist professional Three-view drawings shader?(not find yet)

Related

How to set specific angle between 2 game objects in unity

SCENARIO
I am creating an app where I have to show chemical bonding between atoms(which are game objects). I am using Leap motion hands for spawning and making atoms collide to form molecules. Now the bond between atoms are made using cylinder game objects.
Also when bond(cylinder) is spawned correctly it is joined to atoms' game objects using fixed joints.
All these things are working correctly and as intended.
PROBLEM:
As one atom can form bond with multiple atoms so I want to maintain a certain angle between each bonded atoms.(for eg. in chemistry CH4 molecule's atoms are separated by around 105 degrees).
So I want to achieve the same effect in my app too by separating each atom in molecule by certain angle.
What I currently have only create molecule properly but doesn't have anything to separate according to angle.
This is what I am doing currently.
private IEnumerator SetAtomPosition(Transform atomOne, Transform atomTwo, Transform cylinder)
{
cylinder.gameObject.GetComponent<Rigidbody>().isKinematic = true;
while (Vector3.Distance(atomOne.position, atomTwo.position) > atomDistance)
{
atomTwo.position = Vector3.MoveTowards(atomTwo.position, atomOne.position, Time.deltaTime * 0.1f);
yield return 0;
}
while (Vector3.Distance(atomOne.position, atomTwo.position) < atomDistance)
{
atomTwo.position = Vector3.MoveTowards(atomTwo.position, -atomTwo.forward * 1000f, Time.deltaTime * 0.1f);
yield return 0;
}
cylinder.transform.position = (atomTwo.position - atomOne.position) / 2.0f + atomOne.position;
cylinder.transform.rotation = Quaternion.FromToRotation(Vector3.up, atomTwo.position - atomOne.position);
#region JoinAtoms
cylinder.gameObject.AddComponent<FixedJoint>();
cylinder.gameObject.AddComponent<FixedJoint>();
var cylinderJoints = cylinder.GetComponents<FixedJoint>();
cylinderJoints[0].connectedBody = atomOne.GetComponent<Rigidbody>();
atomOne.GetComponent<Atom>().joint = cylinderJoints[0];
//cylinderJoints[0].breakForce = breakForce;
cylinderJoints[1].connectedBody = atomTwo.GetComponent<Rigidbody>();
atomTwo.GetComponent<Atom>().joint = cylinderJoints[1];
KinematicToggle(cylinder.gameObject);
cylinder.GetComponent<Rigidbody>().mass = 10f;
#endregion
yield return null;
}
And this is what it looks like currently
I want those 4 white spheres to be aligned around black sphere(Carbon atom).
What I want is something similar to this image.

Game object not rotating to correct specified angle [duplicate]

This question already has answers here:
Rotate GameObject over time
(2 answers)
Closed 5 years ago.
I am using the following code to rotate my game objects over a given period of time:
IEnumerator RotateMe(Vector3 byAngles, float inTime)
{
Quaternion fromAngle = transform.rotation ;
Quaternion toAngle = Quaternion.Euler(transform.eulerAngles + byAngles) ;
for(float t = 0f ; t < 1f ; t += Time.deltaTime/inTime)
{
transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t) ;
yield return null ;
}
}
public void runCoroutine(Vector3 destination) {
StartCoroutine(RotateMe(destination, 0.5f));
}
then I call it in the following way:
runCoroutine(new Vector3(0,0,-90));
I realized from testing that my game objects are not rotating to the specified angles, but close them. Not really sure what is causing this.
I would have say that using Lerp method is better. For exact time related things, you'd have to introduce the lerp's rate.
transform.rotation = Quaternion.Lerp(fromAngle, toAngle, 1/value)
you can control the "value" to control the rate of rotation. I usually use this method to have a more controlled rotation.
NOTE: Make sure the lerping is done in a "per-frame" method call; update/fixed-update/late-update

How to have a sprite follow another "within bounds"

I want to create an eyeball that follows the user. In this sense, the eye should follow the position of the user but should only be able to move within certain bounds (The eye socket). The code I wrote below works, but its very choppy.
if(dist <= socketRadius - self.aEye.size.width/2.2){
lastPosition = self.aEye.position
self.aEye.physicsBody?.velocity = CGVector(dx:theVec.dx * eyeMoveSpeed, dy:theVec.dy * eyeMoveSpeed)
}
else{
let toCenterVector = normalizeVector( CGVector(dx:(self.socket.position.x - self.aEye.position.x), dy:(self.socket.position.y - self.aEye.position.y)*3 ))
self.aEye.physicsBody?.velocity = toCenterVector
print(toCenterVector)
print("Out")
}
(dist is the distance from the eyeball to the eyesocket center)
Is there a way to have a smooth flow of the eyeball around its socket to follow the user's position?
You can use SKConstraints to achieve this. Something like:
let rangeToCenterSprite = SKRange(lowerLimit: 80, upperLimit: 90)
var distanceConstraint: SKConstraint
distanceConstraint = SKConstraint.distance(rangeToCenterSprite, toNode: SpriteNodeInEyeCenter)
EyeBallSprite.constraints = [distanceConstraint]

Unity3D: Simultaneous Mesh update

I'm facing a problem regarding the update of several meshes materials.
I'm developing a projection mapping app, currently I have 3 planes on my surface, each has 4 points that define their position in space (each point, named DestinationPoint is located at the edge of the plane's corners representing the mesh). By moving (manually, using the OnMouseDown() and OnMouseDrag() functions) each point, the mesh is updated accordingly so that each corner follows each of the point (the goal is matches a real world surface.)
So that I don't have to do this calibration each time, I'm saving the values (local position property) of these 12 points (3 planes * 4 points) in a XML file. The saving/loading process of the XML file is working just fine, all points are automatically moved to the positions previously saved in the XML file. The problem arises when Unity updates each mesh material, it is only updating ONE mesh.
For example, this is the saved scene, saved into a XML file, with 3 planes, each having 4 points represented by the white spheres.
This is the scene loaded from the XML file. The points are moved into the proper position, yet the mesh isn't updated.
The function that loads the XML file is the following:
void LoadScenario(){
filePath = Application.dataPath + "/XmlData/"+scenario+".xml";
XmlReader reader = XmlReader.Create(filePath);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNodeList Surfaces = xmlDoc.GetElementsByTagName("Surfaces");
/* XML file structure
*
* <Surfaces>
<ProjectionSurface1>
<DestinationPoints>
<DP0>
<Position>-8.28037,18.33852,10.06745</Position>
</DP0>
<DP1>
<Position>-31.55436,-3.485761,3.270439</Position>
</DP1>
<DP2>
<Position>38.00045,-1.380948,4.482903</Position>
</DP2>
<DP3>
<Position>30.65092,19.90506,10.96985</Position>
</DP3>
</DestinationPoints>
</ProjectionSurface1>
</Surfaces>
*/
for(int surface = 0; surface < Surfaces.Count; surface++){
// There is only 1 type of Surface, so only 1 node for now...
XmlNode NodeSurface = Surfaces.Item(surface);
// Get List of Projection Surfaces
XmlNodeList allProjSurfaces = NodeSurface.ChildNodes;
//Debug.Log("Number of Proj Surfaces = " + allProjSurfaces.Count);
for(int projSurf = 0 ; projSurf < allProjSurfaces.Count; projSurf++){
XmlNode nodeProjSurface = allProjSurfaces.Item(projSurf);
string activeProjSurfStr = nodeProjSurface.Name;
//Debug.Log("Projection Surface: " + nodeProjSurface.Name);
// Get the DestinationPoints node
XmlNode nodeDestPoints = nodeProjSurface.FirstChild;
// Get all DPs node list
XmlNodeList allDPs = nodeDestPoints.ChildNodes;
for(int dp = 0; dp < allDPs.Count; dp++){
XmlNode nodeDP = allDPs.Item(dp);
XmlNode nodePos = nodeDP.FirstChild;
string dpStr = nodeDP.Name;
Debug.Log("dpStr: " + dpStr);
string[] split_position = nodePos.InnerText.Split(',');
/*Debug.Log("ProjectionSurface : " + nodeProjSurface.Name +
" with " + nodeDP.Name +
" ,with PosX: " + float.Parse(split_position[0]) +
" ,with PosY: " + float.Parse(split_position[1]) +
" ,with PosZ: " + float.Parse(split_position[2]));*/
float xmlXPos = float.Parse(split_position[0]);
float xmlYPos = float.Parse(split_position[1]);
float xmlZPos = float.Parse(split_position[2]);
Vector3 xmlPosVec = new Vector3(xmlXPos, xmlYPos, xmlZPos);
List <GameObject> dpList = sleManager.listOfDestPoints;
int multiplier = destControl.ReturnModifier(projSurf+1);
dpList[dp+multiplier].transform.localPosition = xmlPosVec;
GameObject dpActiveObj = dpList[dp+multiplier].gameObject;
}
}
}
reader.Close();
// Test to force an update to all 3 projection surfaces meshes
GameObject dp0 = sleManager.listOfDestPoints[0];
GameObject dp4 = sleManager.listOfDestPoints[4];
GameObject dp8 = sleManager.listOfDestPoints[8];
destControl.Run(dp0);
Debug.Log("0");
destControl.Run(dp4);
destControl.Run(dp8);
}
}
The function Run(GameObj obj) that I'm using in the end has the main goal of updating the material properties of obj in the argument and is as follows:
public void Run(GameObject dpObj){
Debug.Log("Run com arg obj name: " + dpObj.gameObject.name);
manager.indexChanged = true;
string activeDPStr = dpObj.name;
string activeProjSurfStr = dpObj.transform.root.ToString();
manager.activeProjSurfObj = ReturnActiveProjSurf(dpObj);
manager.activePlaneObj = ReturnActivePlaneObj(manager.activeProjSurfObj);
string activePlaneStr = manager.activePlaneObj.name;
manager.activeProjSurf = int.Parse(activeProjSurfStr[17].ToString());
manager.modifier = ReturnModifier(manager.activeProjSurf);
manager.activeIndex = int.Parse(activeDPStr[2].ToString()) + manager.modifier;
manager.meshMaterial = manager.activePlaneObj.renderer.material;
}
The list "listOfDestPoints" contains all existing destination points. Keep in mind each plane has 4 points, so every 4 members in the list, the target plane changes.
Now, if I try to run do:
destControl.Run(dp0); // Updates Plane 1, works just fine.
But if I try:
destControl.Run(dp0);
destControl.Run(dp4); // Does not update Plane 1, only Plane 2.
p.s: Sorry about the wall of text!
Just solved it with:
yield return new WaitForSeconds(.25f);
Inside the LoadScenario() function. Seems For cycle was faster than the update function so only the last member of the For cycle was truly updated.

Square collision detection iPhone

I have this game where i need to know if the ball has hit a wall on the side (to bounce back on the x-axis) or on the top (to bounce back on the y-axis, like a bounce on the ground). They work fine individually, but when I uncomment both of them, it dosen't work. (I think this is because the code is 'overlapping'?). Anyway, here is the code, and any help is fantastic:
if (CGRectIntersectsRect(guy.frame, wall_01.frame)) {
if (guy.frame.origin.y+guy.frame.size.height >= wall_01.frame.origin.y && guy.frame.origin.y <= wall_01.frame.origin.y+wall_01.frame.size.height) {
iJump *= kRestitution;
}
if (guy.frame.origin.x+guy.frame.size.width >= wall_01.frame.origin.x && guy.frame.origin.x <= wall_01.frame.origin.x+wall_01.frame.size.width) {
jJump *= kRestitution;
}
}
assuming wall is on the left side and the y increases from top to bottom
CGFloat leftWall = someXPosition;
CGFloat ground = someYPosition;
CGFloat ballLeft = CGRectGetMinX(guy.frame);
CGFloat ballRight = CGRectGetMaxX(guy.frame);
CGFloat ballBottom = CGRectGetMaxY(guy.frame);
if (ballLeft <= leftwall && ballBot >= ground){
//ball hit corner ?
} else if (ballLeft <= leftWall){
//passed or touched wall
} else if (ballBot >= ground){
//passed or touched ground
}