How do I make a stationary image out of particles in LSL? - linden-scripting-language

LSL (Linden Scripting Language) allows for various particle effects using the llParticleSystem function. What are the right parameters to give to that function in order to make a non-moving particle-based image hover over the prim?
(This question was asked in the Script Academy discussion group today. I'm reposting the question and my answer here to help get more LSL users into Stack Overflow.)

The following script will create a stationary hovering image out of particles, using the first texture found in the contents of the prim.
ParticleImage(string tex, vector scale)
{
list params;
//set texture and size
params += [PSYS_SRC_TEXTURE, tex];
params += [PSYS_PART_START_SCALE, scale];
//make particles follow source
params += [PSYS_PART_FLAGS, PSYS_PART_FOLLOW_SRC_MASK];
//use drop pattern, which has no velocity
params += [PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP];
llParticleSystem(params);
}
default
{
state_entry()
{
//make the prim invisible
llSetAlpha(0.0, ALL_SIDES);
if (llGetInventoryNumber(INVENTORY_TEXTURE))
{
string tex = llGetInventoryName(INVENTORY_TEXTURE, 0);
ParticleImage(tex, <1.0, 1.0, 0.0>);
}
}
}

Related

Get texture coordinates of mouse position in SDL2?

I have the strict requirement to have a texture with resolution (let's say) of 512x512, always (even if the window is bigger, and SDL basically scales the texture for me, on rendering). This is because it's an emulator of a classic old computer assuming a fixed texture, I can't rewrite the code to adopt multiple texture sizes and/or texture ratios dynamically.
I use SDL_RenderSetLogicalSize() for the purpose I've described above.
Surely, when this is rendered into a window, I can get the mouse coordinates (window relative), and I can "scale" back to the texture position with getting the real window size (since the window can be resized).
However, there is a big problem here. As soon as window width:height ratio is not the same as the texture's ratio (for example in full screen mode, since the ratio of modern displays would not match of the ratio I want to use), there are "black bars" at the sides or top/bottom. Which is nice, since I want always the same texture ratio, fixed, and SDL does it for me, etc. However I cannot find a way to ask SDL where is my texture rendered exactly inside the window based on the fixed ratio I forced. Since I need the position within the texture only, and the exact texture origin is placed by SDL itself, not by me.
Surely, I can write some code to figure out how those "black bars" would change the origin of the texture, but I can hope there is a more simple and elegant way to "ask" SDL about this, since surely it has the code to position my texture somewhere, so I can re-use that information.
My very ugly (can be optimized, and floating point math can be avoided I think, but as the first try ...) solution:
static void get_mouse_texture_coords ( int x, int y )
{
int win_x_size, win_y_size;
SDL_GetWindowSize(sdl_win, &win_x_size, &win_y_size);
// I don't know if there is more sane way for this ...
// But we must figure out where is the texture within the window,
// which can be changed since the fixed ratio versus the window ratio (especially in full screen mode)
double aspect_tex = (double)SCREEN_W / (double)SCREEN_H;
double aspect_win = (double)win_x_size / (double)win_y_size;
if (aspect_win >= aspect_tex) {
// side ratio correction bars must be taken account
double zoom_factor = (double)win_y_size / (double)SCREEN_H;
int bar_size = win_x_size - (int)((double)SCREEN_W * zoom_factor);
mouse_x = (x - bar_size / 2) / zoom_factor;
mouse_y = y / zoom_factor;
} else {
// top-bottom ratio correction bars must be taken account
double zoom_factor = (double)win_x_size / (double)SCREEN_W;
int bar_size = win_y_size - (int)((double)SCREEN_H * zoom_factor);
mouse_x = x / zoom_factor;
mouse_y = (y - bar_size / 2) / zoom_factor;
}
}
Where SCREEN_W and SCREEN_H are the dimensions of the my texture, quite misleading by names, but anyway. Input parameters x and y are the window-relative mouse position (reported by SDL). mouse_x and mouse_y are the result, the texture based coordinates. This seems to work nicely. However, is there any sane solution or a better one?
The code which calls the function above is in my event handler loop (which I call regularly, of course), something like this:
void handle_sdl_events ( void ) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_MOUSEMOTION:
get_mouse_texture_coords(event.motion.x, event.motion.y);
break;
[...]

Aligning a card array in-game

I'm creating a tcg (trading card game) and I would like to know how can I change the layout of the cards while playing. I mean that the cards will be spread in line aligned to the center of the screen both vertically and horizontaly, on a canvas, and when I draw/dismiss a card I would like the cards to fill in the space and align again in game. How can I do that? any ideas? I thought of a solution about when your turn begins (Start from the center of the screen then step back the length of a step X the number of cards / 2 and then spawn the cards one after another), but I can't figure out how to change the alignment of cards when you dismiss one of them without loading them all again...
Image for example
Using the same method you used for the initial position you should be able to get the new position. Now you have two positions for each card: oldPos and newPos.
Your cards are already instantiated. Their positions are stored in Transform.position. Your goal is to move from oldPos to newPos. The simplest way would be:
myCard.transform.position = newPos;
This will instantly move your cards to their new positions. However, it's not common to teleport your objects because it does not often present good feelings to users. A better solution is to smoothly move the object from a position to another.
To do this, you can move around an existing object by transform.Translate(new Vector3());, where the Vector3 will decide its moving speed. The method Translate() is doing position += movementDirection * movementAmount as you would've expected.
Moving any object over frames is called Animation. There are techniques for animation to make movements look more better (look faster than it really is, or look natural). One common method from mathematics is called linear interpolation, or lerp. Using lerp, you can easily compute intermediate points between two end-positions, and it will look natural and nice if you put your objects along the points you calculated. I believe this is what you are looking for.
========
Edit:
Here's an example of how this could be achieved. Note that Card is moving by the same amount of distance per frame in this example. Using lerp (ease-in, ease-out, etc), you could make this animation even better.
Another point I would like you to note is that I'm doing if (Vector2.Distance(nextPosition, transform.position) < 10), not if(oldPosition.equals(newPosition)). The reason is that equals() is not safe to compare floats because they are often stored as 0.4999999 and 0.50001 instead of 0.5 and 0.5. So the best way of checking floats is to test if they are "Close Enough" to each other.
Finally, you could improve the following code may improve in MANY DIFFERNET WAYS. For instnace:
Destroy() and Instantiate() is very slow operations and you
should use Object Pooling because you know you will perform these
operations constantly.
The movement of Card could be improved by better animation technique like lerp.
There may be other ways of storing List<Card> Cards
OnCardClick() is using FindObjectOfType<CardSpawner>().OnCardDeleted(this) and this requires Card to know about CardSpawner. This is called Tight Coupling, which is known as evil. There are a lot of discussions you can find why this is bad. A recommended solution would be to use event (better UnityEvent in Unity3d).
CardSpawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CardSpawner : MonoBehaviour
{
[SerializeField] GameObject CardParent;
[SerializeField] GameObject CardPrefab;
Vector2 DefaultSpawnPosition = new Vector2(Screen.width / 2f, Screen.height / 10f);
List<Card> Cards = new List<Card>();
public void OnClickButton()
{
SpawnNewCard();
AssignNewPositions();
AnimateCards();
}
public void OnCardDeleted(Card removedCard)
{
Cards.Remove(removedCard);
AssignNewPositions();
AnimateCards();
}
void SpawnNewCard()
{
GameObject newCard = (GameObject)Instantiate(CardPrefab, DefaultSpawnPosition, new Quaternion(), CardParent.GetComponent<Transform>());
Cards.Add(newCard.GetComponent<Card>());
}
void AssignNewPositions()
{
int n = Cards.Count;
float widthPerCard = 100;
float widthEmptySpaceBetweenCards = widthPerCard * .2f;
float totalWidthAllCards = (widthPerCard * n) + (widthEmptySpaceBetweenCards * (n-1));
float halfWidthAllCards = totalWidthAllCards / 2f;
float centreX = Screen.width / 2f;
float leftX = centreX - halfWidthAllCards;
for (int i = 0; i < n; i++)
{
if (i == 0)
Cards[i].nextPosition = new Vector2(leftX + widthPerCard / 2f, Screen.height / 2f);
else
Cards[i].nextPosition = new Vector2(leftX + widthPerCard / 2f + ((widthPerCard + widthEmptySpaceBetweenCards) * i), Screen.height / 2f);
}
}
void AnimateCards()
{
foreach (Card card in Cards)
card.StartMoving();
}
}
Card.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Card : MonoBehaviour
{
public Vector2 oldPosition;
public Vector2 nextPosition;
bool IsMoving;
void Update ()
{
if (IsMoving)
{
int steps = 10;
Vector2 delta = (nextPosition - oldPosition) / steps;
transform.Translate(delta);
if (Vector2.Distance(nextPosition, transform.position) < 10)
IsMoving = false;
}
}
public void StartMoving()
{
IsMoving = true;
oldPosition = transform.position;
}
public void OnCardClick()
{
UnityEngine.Object.Destroy(this.gameObject);
Debug.Log("AfterDestroy");
FindObjectOfType<CardSpawner>().OnCardDeleted(this);
}
}

Unity3D - Playback object array of position (with dynamic velocity)

We own two objects in the scene. One follows the mouse position on the screen, and the object 2 in turn follows the route object 1 did. We are storing the positions covered by the object 1 and causing the object 2 play them.
When you run the game, an object follows the other quietly, reproducing the stored position ... but when one object's speed is changed (on mouse click increase velocity) the object 2 can not keep up, as this still following the positions already be cached in the array (including the calculations speed). Please, watch the shot video below:
YouTube: https://youtu.be/_HbP09A3cFA
public class Play : MonoBehaviour
{
public Transform obj;
private List<Recorder> recordList;
private float velocity = 10.0f;
private Transform clone;
void Start()
{
recordList = new List<Recorder>();
clone = obj;
}
void Update()
{
if (Input.GetMouseButton(0))
{
velocity = 20.0f;
}
else {
velocity = 10.0f;
}
var dir = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position);
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward), 180 * Time.deltaTime);
transform.position += transform.right * Time.deltaTime * velocity;
Camera.main.transform.position = new Vector3(transform.position.x, transform.position.y, Camera.main.transform.position.z);
recordList.Insert(0, new Recorder
{
Position = transform.position,
Rotation = transform.rotation,
Velocity = velocity
});
var x = 8;
if (x < recordList.Count)
{
clone.position = recordList[x].Position;
clone.rotation = recordList[x].Rotation;
clone.position += clone.right * Time.deltaTime * velocity;
}
if (recordList.Count > x)
recordList.RemoveRange(x, recordList.Count - x);
}
}
public class Recorder
{
public Vector3 Position{get;set;}
public Quaternion Rotation{get;set;}
public float Velocity{get;set;}
}
How can we play the positions stored always with the speed of the object 1?
Summary:
If the object 1 is slowly moving object 2 as well;
If the object 2 is running, the object 2 should do the route at a faster speed to always follow the object 1;
Thanks in advance.
If i understood correctly you might want to consider using Queue<T> instead of List<T>. I think it would be a better suited datatype as it represents a FIFO collection (first in, first out), which is how you use List anyway. You can add elements with Enqueue(T) to the end of the queue and always get the first item with Dequeue() (it also removes it). As for Stack<T> (the opposite), there is also a Peek() function which lets you "preview" the next element.
Another thing, it depends on distance and speed, but i have the feeling that storing the position of every frame could become a bit excessive (maybe im just overly concerned though)
I think the issue with your code is that you always get the 8th element of the List.

How to find boundary pixels of each connected component in an image in opencv

I have an image with text and I want to find boundary pixels of every connected component.Which method should I use in opencv 2.3,I am coding in c.
This function may be just like bwboundaries of matlab.
thanks,
In OpenCV 2.3, the function you want is called cv::findContours. Each contour (which is the boundary of the connected component) is stored as a vector of points. Here's how to access the contours in C++:
vector<vector<Point> > contours;
cv::findContours(img, contours, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (size_t i=0; i<contours.size(); ++i)
{
// do something with the current contour
// for instance, find its bounding rectangle
Rect r = cv::boundingRect(contours[i]);
// ...
}
If you need the full hierarchy of contours, including holes inside components and so forth, the call to findContours is like this:
vector<vector<Point> > contours;
Hierarchy hierarchy;
cv::findContours(img, contours, hierarchy, cv::RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
// do something with the contours
// ...
Note: the parameter CV_CHAIN_APPROX_SIMPLE indicates that straight line segments in the contour will be encoded by their end-points. If instead you want all contour points to be stored, use CV_CHAIN_APPROX_NONE.
Edit: in C you call cvFindContours and access the contours like this:
CvSeq *contours;
CvMemStorage* storage;
storage = cvCreateMemStorage(0);
cvFindContours(img, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
CvSeq* c;
for(c=contours; c != NULL; c=c->h_next)
{
// do something with the contour
CvRect r = cvBoundingRect(c, 0);
// ...
}
c->h_next points to the next contour at the same level of the hierarchy as the current contour, and c->v_next points to the first contour inside the current contour, if there is any. Of course, if you use CV_RETR_EXTERNAL like above, c->v_next will always be NULL.
You can use cvFindContours (this is the version 1.0 call, but there should be a similar call in 2.3)
There is no such function implemented in OpenCV.
You should either searching into morphology operations (substractions of your image and the same one dilated) or have a look at the cvbloblib
http://opencv.willowgarage.com/wiki/cvBlobsLib
It has been developed for this very purpose ;).

WPF 3D - Detirmine whether a ModelVisual3D is being clipped inside it's Viewport3D

I have a cube rendering inside a Viewport3D and i need to know a way to find out whether ALL of the cube is visible to the user.
Edit:Just to be clear,..I'm not talking about clipping because of the near/far plane distance here. I mean the cube is to tall or wide to fit in the cameras field of view.
Any help would be massively appreciated!
Thanks in advance.
I can't offer a solution but I can, perhaps, point you in the right direction.
What you need to get hold of is the extent of the 2D projection of the cube on the view plane. You can then do a simple check on the min and max X & Y values to see whether the whole of the cube is visible.
Adding a tolerance factor to the extent will take care of any rounding errors.
EDIT: I have just done a Google search for "2D projection WPF" and this link came up. It looks like it addresses what you want.
FURTHER EDIT: I've copied the relevant section of code from the above link here.
public static Rect Get2DBoundingBox(ModelVisual3D mv3d)
{
bool bOK;
Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);
bool bFirst = true;
Rect r = new Rect();
if (mv3d.Content is GeometryModel3D)
{
GeometryModel3D gm3d = (GeometryModel3D) mv3d.Content;
if (gm3d.Geometry is MeshGeometry3D)
{
MeshGeometry3D mg3d = (MeshGeometry3D)gm3d.Geometry;
foreach (Point3D p3d in mg3d.Positions)
{
Point3D pb = m.Transform(p3d);
Point p2d = new Point(pb.X, pb.Y);
if (bFirst)
{
r = new Rect(p2d, new Size(1, 1));
bFirst = false;
}
else
{
r.Union(p2d);
}
}
}
}
return r;
}
I remember a tutorial on frustum culling on flipcode.
Flipcode - Frustum Culling
I hope it helps.
I can think of doing something similar to this:
Check the nearest point of the cube related to the camera and check if it's being clipped from the near clipping plane.
The nearest point from the camera I can think of is one of this points composing the cube. So you have to check each of the 6 points of the cube and check if they are being clipped. If none of them are, then your cube if fully visible
Oh, and obviously you have to check against the far clipping plane too.
The code is simple:
for each point of cube do
if !(point is in farClippingPlane and nearClippingPlane)
return false;
end if
end for
return true

Resources