I would to apply margin on image that use float property like this:
<img style="float:left;" ...>
as HTML, and this is the scss:
$flottant: left;
#if $flottant == left {
img {
// Cas de l'image en float left
margin: 0 em(10px) 0 0;
}
} #else {
margin: 0;
}
But I don't know how to target the float propertie of the image...
If someone know about it.
Thanks
I try to evaluate the float property for image.
EDIT: I don't know how to include this code into a if/else condition, but I think it's a starting point to make difference between images with float and no float.
img[style*="float: left"] {
// Cas de l'image en float left
margin: 0 em(10px) 0 0;
}
img{margin: 0;}
I don't think I clearly understand the question, but here is how I would trigger float property to apply the margin :
img {
float: left;
margin: 0 10px 0 0;
}
img[style*="float: right"] {
float: right;
margin: 0;
}
Hope it helps
Related
I wish to draw a simple mouse trail using fragment shaders, similar in appearance to drawing the following in processing (omitting the step of clearing the canvas). I cannot wrap my head around the setup necessary to achieve this.
// processing reference using cursor as paintbrush
void setup () {
size(400, 400);
background(255);
fill(0);
}
void draw () {
ellipse(mouseX, mouseY, 20, 20);
}
Here's my vain approach, based on this shadertoy example:
I draw a simple shape at cursor position
void main(void) {
float pct = 0.0;
pct = distance(inData.v_texcoord.xy, vec2(mouse.x, 1.-mouse.y)) * SIZE;
pct = 1.0 - pct - BRIGHTNESS;
vec3 blob = vec3(pct);
fragColor = vec4( blob, 1.0 );
}
Then my confusion begins. My thinking goes that I'd need to mix the output above with a texture containing my previous pass. This creates at least a solid trail, albeit copying the previous pass only within a set distance from the mouse position.
#shader pass 1
void main(void) {
float pct = 0.0;
pct = distance(inData.v_texcoord.xy, vec2(mouse.x, 1.-mouse.y)) * SIZE;
pct = 1.0 - pct - BRIGHTNESS;
vec3 blob = vec3(pct);
vec3 stack = texture(prevPass, inData.v_texcoord.xy).xyz;
fragColor = vec4( blob*.1 + (stack*2.), 1.0 );
}
#shader pass 2
void main(void) {
fragColor = texture(prevPass,inData.v_texcoord);
}
Frankly, I'm a little bit in the blue about how to draw without data and "stack" previous draw calls in webgl on a conceptual level, and I'm having a hard time finding beginner documentation.
I would be grateful if someone could point me towards where my code and thinking becomes faulty, or point me towards some resources.
What you need to do is:
After doing your first pass rendering (i.e. making an ellipse at the cursor position), copy the contents of the framebuffer to a different image.
Then pass this image as an sampler input to the next pass. Notice how that shadertoy example ahs 2 images.
You can make a simple HTML/Javascript trail with this code:
<!DOCTYPE html>
<style>
.trail { /* className for trail elements */
position: absolute;
height: 6px; width: 6px;
border-radius: 3px;
background: teal;
}
body {
height: 300px;
}
</style>
<body>
<script>
document.body.addEventListener("mousemove", moved);
// create, style, append trail elements
var trailElements = [];
var numOfTrailElements = 10;
for (var i = 0; i < numOfTrailElements; i++) {
var element = document.createElement('div');
element.className = 'trail';
document.body.appendChild(element);
trailElements.push(element);
}
// when mouse moves, display trail elements in wake of mouse pointer
var counter = 0; // current trail element index
function moved(event) {
trailElements[counter].style.left = event.clientX + 'px';
trailElements[counter].style.top = event.clientY + 'px';
if (counter == 9) {
counter = 0;
} else {
counter += 1;
}
}
</script>
</body>
<!doctype html>
<style>
.trail { /* className for the trail elements */
position: absolute;
height: 6px; width: 6px;
border-radius: 3px;
background: black;
}
body {
height: 300px;
}
</style>
<body>
<script>
var dots = [];
for (var i = 0; i < 12; i++) {
var node = document.createElement("div");
node.className = "trail";
document.body.appendChild(node);
dots.push(node);
}
var currentDot = 0;
addEventListener("mousemove", function(event) {
var dot = dots[currentDot];
dot.style.left = (event.pageX - 3) + "px";
dot.style.top = (event.pageY - 3) + "px";
currentDot = (currentDot + 1) % dots.length;
});
</script>
</body>
I have a grid of 300x300 cells. I am checking each cell individually which means I am checking 90000 cells atleast every second. Now, I know, one second is pretty fast considering the cpu is going through 300^2 different cells. But this stuff just isn't fast enough. I watched a guy on youtube who got his simulation to update every 20 ms. And he was running 512^2 cells. How is this possible? Optimizations? Is my computer a potato? I'll show my code if anyone wants to see exactly what i'm doing.
for (int y = GY; y >= 0; y--)
for (int x = 0; x < GX; x++) {
cell* cell_pointer = &grid[x][y];
if (grid[x][y].CellT == type::SAND) {
if (grid[x][y+1].CellT == type::AIR) {
if (y+1 > GY-1) {
continue;
}
cell* cell_below = &grid[x][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
else if (grid[x+1][y+1].CellT == type::AIR) {
cell* cell_below = &grid[x+1][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
else if (grid[x-1][y+1].CellT == type::AIR) {
cell* cell_below = &grid[x-1][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
}
}
The code above is my update function. I am updating the cells bottom to top, left to right. It's a sand simulation which is why we're checking the bottom left, bottom right as well as the bottom neighboring cells.
//Square//
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);
//////////
int X = floor(mousePos.x/r.w);
int Y = floor(mousePos.y/r.h);
if (left) {
grid[X][Y].CellT = type::SAND;
grid[X][Y].Color ={ 255,0,0 };
}
if (right) {
grid[X][Y].CellT = type::WALL;
grid[X][Y].Color ={ 0,255,0 };
}
for (int y = 0; y < GY; y++)
for (int x = 0; x < GX; x++) {
cell* cell_pointer = &grid[x][y];
SDL_SetRenderDrawColor(renderer, cell_pointer->Color.r, cell_pointer->Color.g, cell_pointer->Color.b, 255);
r.x = cell_pointer->PosG.x;
r.y = cell_pointer->PosG.y;
SDL_RenderFillRect(renderer, &r);
}
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
The code above is my draw function. I am using SDL as my graphics API. I am getting the mouse position relative to the grids so that when I click left or right mouse buttons I can draw a sand cell or a wall cell. So I am checking each cell individually top to bottom and left to right and then drawing a square individually where the cell's position is.
What I'm trying to do is generate a grid with less:
.grid {
/**
* #link http://lesscss.org/functions/#list-functions-each
*/
#selectors: 2, 3, 4, 5;
each(#selectors, {
&.--cols-#{value} {
#width: if((#value < 3), 100% / #value, 50%); // of #value = 2 ?
.list {
flex-basis: ~"calc(#{width} - 1px)";
}
.item {
max-width: ~"calc(#{width} - 1px)";
width: 100%;
}
}
});
}
But somehow less is generating then calc(50% - 1px) for all columns. So the question is - what am I doing wrong?
P.S. You can test here: http://lesscss.org/less-preview/
It should have been: #width: if((#value < 3), 50%, 100% / #value);
Thanks to #seven-phases-max.
I have created a particle system in c++ using Qt which includes gravity. I would like to include a bounding box so that the system can also include collisions however I cannot seem to get it to work. Here is my .h code:
typedef struct {
int top;
int bottom;
int left;
int right;
}BoundingBox;
BoundingBox makeBoundingBox(int top, int bottom, int left, int right);
.cpp:
BoundingBox makeBoundingBox(int top, int bottom, int left, int right)
{
BoundingBox boundingBox;
boundingBox.top = top;
boundingBox.bottom = bottom;
boundingBox.left = left;
boundingBox.right = right;
return boundingBox;
}
I have then updated the bounding box in my emitter class using this loop:
for(int i=0; i<m_numParticles; ++i)
{
if (m_pos.m_y >= _boundingBox.top)
{
m_dir.m_y = (-1)*(m_dir.m_y);
}
if (m_pos.m_y <= _boundingBox.bottom)
{
m_dir.m_y = (-1)*(m_dir.m_y);
}
if (m_pos.m_x <= _boundingBox.left)
{
m_dir.m_x = (-1)*(m_dir.m_x);
}
if (m_pos.m_x >= _boundingBox.right)
{
m_dir.m_x = (-1)*(m_dir.m_x);
}
m_particles[i].update(m_gravity, _boundingBox);
And have set the bounding box in my window as so:
m_emitter->setBoundingBox(makeBoundingBox(m_height, 0, 0, m_width));
I am not getting any errors however it doesn't seem to be working,
Any advice would be appreciated
Thanks
Assuming that decreasing X means going towards left and decreasing Y means going towards top, your conditions seem incorrect. I would also update the position alongside the velocity to make sure it doesn't get triggered multiple times in a row.
Example for the Y coordinate:
// Are we going up too much?
if (m_pos.m_y < _boundingBox.top)
{
m_dir.m_y = (-1)*(m_dir.m_y);
m_pos.m_y = _boundingBox.top + 1;
}
// Or are we going down too much?
else if (m_pos.m_y > _boundingBox.bottom)
{
m_dir.m_y = (-1)*(m_dir.m_y);
m_pos.m_y = _boundingBox.bottom - 1;
}
Shouldn't:
m_emitter->setBoundingBox(makeBoundingBox(m_height, 0, 0, m_width));
Be:
m_emitter->setBoundingBox(makeBoundingBox(0, m_height, 0, m_width));
This code sample here:
import QtQuick 2.0
Item {
width: 200; height: 200
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
}
}
Will produce this output:
Now I want to apply a 3D rotation from the center of this green rectangle. First, I want to rotate on X by -45 degrees (bowing down), then on Y by -60 degrees (turning left).
I used the following c++ code snipped using GLM on the side to help me calculate the axis and angle:
// generate rotation matrix from euler in X-Y-Z order
// please note that GLM uses radians, not degrees
glm::mat4 rotationMatrix = glm::eulerAngleXY(glm::radians(-45.0f), glm::radians(-60.0f));
// convert the rotation matrix into a quaternion
glm::quat quaternion = glm::toQuat(rotationMatrix);
// extract the rotation axis from the quaternion
glm::vec3 axis = glm::axis(quaternion);
// extract the rotation angle from the quaternion
// and also convert it back to degrees for QML
double angle = glm::degrees(glm::angle(quaternion));
The output of this little C++ program gave me an axis of {-0.552483, -0.770076, 0.318976} and an angle of 73.7201. So I updated my sample code to this:
import QtQuick 2.0
Item {
width: 200; height: 200
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
transform: Rotation {
id: rot
origin.x: 50; origin.y: 50
axis: Qt.vector3d(-0.552483, -0.770076, 0.318976)
angle: 73.7201
}
}
}
Which give me exactly what I wanted to see:
So far so good. Now comes the hard part. How do I animate this? For example, if I want to go from {45.0, 60.0, 0} to {45.0, 60.0, 90.0}. In other word, I want to animate from here
to here
I plugged that target rotation here
// generate rotation matrix from euler in X-Y-Z order
// please note that GLM uses radians, not degrees
glm::mat4 rotationMatrix = glm::eulerAngleXYZ(glm::radians(-45.0f), glm::radians(-60.0f), glm::radians(90.0f);
// convert the rotation matrix into a quaternion
glm::quat quaternion = glm::toQuat(rotationMatrix);
// extract the rotation axis from the quaternion
glm::vec3 axis = glm::axis(quaternion);
// extract the rotation angle from the quaternion
// and also convert it back to degrees for QML
double angle = glm::degrees(glm::angle(quaternion));
which gave me an axis of {-0.621515, -0.102255, 0.7767} and an angle of 129.007
So I added this animation to my sample
ParallelAnimation {
running: true
Vector3dAnimation {
target: rot
property: "axis"
from: Qt.vector3d(-0.552483, -0.770076, 0.318976)
to: Qt.vector3d(-0.621515, -0.102255, 0.7767)
duration: 4000
}
NumberAnimation {
target: rot;
property: "angle";
from: 73.7201; to: 129.007;
duration: 4000;
}
}
Which 'almost' works. The problem is, if you try it, you will see that the rotation goes completely off its desired rotation axis for the first half of the animation, but fixes itself for the last half of the animation. The starting rotation is good, the target rotation is good, but whatever that happens in between is not good enough. It is better if I use smaller angles like 45 degrees instead of 90 degrees, and is going to be worst if I use larger angles like 180 degrees instead of 45 degrees, where it just spins in random directions until it reaches its final targets.
How do I get this animation to look right between the start rotation and the target rotation?
------------------- EDIT -------------------
I am adding one more criteria: The answer I am looking for must absolutely provide an identical output as the screenshots I provided above.
For example, splitting the 3 rotation axis in 3 separate rotation transforms doesn't give me the right results
transform: [
Rotation {
id: zRot
origin.x: 50; origin.y: 50;
angle: 0
},
Rotation {
id: xRot
origin.x: 50; origin.y: 50;
angle: -45
axis { x: 1; y: 0; z: 0 }
},
Rotation {
id: yRot
origin.x: 50; origin.y: 50;
angle: -60
axis { x: 0; y: 1; z: 0 }
}
]
Will give me this:
Which is incorrect.
I solved my own problem. I completely forgot that Qt doesn't do spherical linear interpolation!!! As soon as I did my own slerp function, it all worked perfectly.
Here's my code for those who are seeking the answer:
import QtQuick 2.0
Item {
function angleAxisToQuat(angle, axis) {
var a = angle * Math.PI / 180.0;
var s = Math.sin(a * 0.5);
var c = Math.cos(a * 0.5);
return Qt.quaternion(c, axis.x * s, axis.y * s, axis.z * s);
}
function multiplyQuaternion(q1, q2) {
return Qt.quaternion(q1.scalar * q2.scalar - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
q1.scalar * q2.x + q1.x * q2.scalar + q1.y * q2.z - q1.z * q2.y,
q1.scalar * q2.y + q1.y * q2.scalar + q1.z * q2.x - q1.x * q2.z,
q1.scalar * q2.z + q1.z * q2.scalar + q1.x * q2.y - q1.y * q2.x);
}
function eulerToQuaternionXYZ(x, y, z) {
var quatX = angleAxisToQuat(x, Qt.vector3d(1, 0, 0));
var quatY = angleAxisToQuat(y, Qt.vector3d(0, 1, 0));
var quatZ = angleAxisToQuat(z, Qt.vector3d(0, 0, 1));
return multiplyQuaternion(multiplyQuaternion(quatX, quatY), quatZ)
}
function slerp(start, end, t) {
var halfCosTheta = ((start.x * end.x) + (start.y * end.y)) + ((start.z * end.z) + (start.scalar * end.scalar));
if (halfCosTheta < 0.0)
{
end.scalar = -end.scalar
end.x = -end.x
end.y = -end.y
end.z = -end.z
halfCosTheta = -halfCosTheta;
}
if (Math.abs(halfCosTheta) > 0.999999)
{
return Qt.quaternion(start.scalar + (t * (end.scalar - start.scalar)),
start.x + (t * (end.x - start.x )),
start.y + (t * (end.y - start.y )),
start.z + (t * (end.z - start.z )));
}
var halfTheta = Math.acos(halfCosTheta);
var s1 = Math.sin((1.0 - t) * halfTheta);
var s2 = Math.sin(t * halfTheta);
var s3 = 1.0 / Math.sin(halfTheta);
return Qt.quaternion((s1 * start.scalar + s2 * end.scalar) * s3,
(s1 * start.x + s2 * end.x ) * s3,
(s1 * start.y + s2 * end.y ) * s3,
(s1 * start.z + s2 * end.z ) * s3);
}
function getAxis(quat) {
var tmp1 = 1.0 - quat.scalar * quat.scalar;
if (tmp1 <= 0) return Qt.vector3d(0.0, 0.0, 1.0);
var tmp2 = 1 / Math.sqrt(tmp1);
return Qt.vector3d(quat.x * tmp2, quat.y * tmp2, quat.z * tmp2);
}
function getAngle(quat) {
return Math.acos(quat.scalar) * 2.0 * 180.0 / Math.PI;
}
width: 200; height: 200
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
transform: Rotation {
id: rot
origin.x: 50; origin.y: 50
axis: getAxis(animator.result)
angle: getAngle(animator.result)
}
}
NumberAnimation
{
property quaternion start: eulerToQuaternionXYZ(-45, -60, 0)
property quaternion end: eulerToQuaternionXYZ(-45, -60, 180)
property quaternion result: slerp(start, end, progress)
property real progress: 0
id: animator
target: animator
property: "progress"
from: 0.0
to: 1.0
duration: 4000
running: true
}
}
You are trying to this in wrong way. You can combine transformations and animate one of it. This way you will achieve exactly what you need.
Another problem I see is that you are writing about degrees and in code I see radians :).
Bottom line this should look like this:
Rectangle {
width: 100; height: 100
anchors.centerIn: parent
color: "#00FF00"
Rectangle {
color: "#FF0000"
width: 10; height: 10
anchors.top: parent.top
anchors.right: parent.right
}
transform: [
Rotation {
id: zRot
origin.x: 50; origin.y: 50;
angle: 0
},
Rotation {
id: xRot
origin.x: 50; origin.y: 50;
angle: 45
axis { x: 1; y: 0; z: 0 }
},
Rotation {
id: yRot
origin.x: 50; origin.y: 50;
angle: 60
axis { x: 0; y: 1; z: 0 }
}
]
NumberAnimation {
running: true
loops: 100
target: zRot;
property: "angle";
from: 0; to: 360;
duration: 4000;
}
}
Result is different from this one on your pictures, but this is result you've messed up degrees and radians. I used transformation described in text, not from your code.