I'm running a sketch with an array of points in 3D space (P3D). I'd like to add an interface to it by drawing text as if it were "onscreen"/2D, only using "X, Y" parameters.
When I tried just adding "text("!##$%", width/2, height/2);" it rendered in 3D space.
Is it possible? I tried "textMode(SCREEN) but doesnt exist in processing 2 anymore.
Here is what I found, I guess on the Processing Forum
You can use:
a PMatrix3D for your 3D content
and code your 2D stuff the plain old way
I wish it helps
PMatrix3D baseMat;
float alpha =0;
void setup() {
size(400, 400, P3D);
// Remember the start model view matrix values
baseMat = getMatrix(baseMat);
}
void draw() {
background(40);
pushMatrix();
camera(0, 0, 400, 0, 0, 0, 0, 1, 0);
directionalLight(255, 255, 255, -100, 150, -100);
ambientLight(40, 40, 40);
// 3D drawing stuff here
rotateY(alpha);
box(100);
alpha += 0.05;
popMatrix();
// Restore the base matrix and lighting ready for 2D
this.setMatrix(baseMat);
ambientLight(255, 255, 255);
// draw 2D stuff here
rect(10, 10, 50, 10);
textSize(25);
text("voila", mouseX, mouseY);
}
A workaround that comes to mind is to create a 2D PGraphic that has the same width/height as your sketch, give it a transparent background, draw your text where you want on it, and then draw the PGraphic onto your real sketch like you would if you were copying over image source data.
Related
I try to draw 2D texts for my 3D world objects with libgdx's camera.project function but have a weird problem.
See the pics below:
As you can see in the pictures, all is well in picture 1 but when I turn around 180 degrees the ball's name (codename 1) is be drawing the blank space also (picture 2). I couldn't get what the problem is and after hours of thinking decided to ask here.
Please help me.
My code is:
public static void drawNames(){
TheGame.spriteBatch.begin();
for(int i = 0; i < TheGame.playerMap.size; i++){
Player ply = TheGame.playerMap.getValueAt(i);
if(!ply.isAlive)
continue;
TheGame.tmpVec.set(ply.getPos().x, ply.getPos().y, ply.getPos().z);
TheGame.cam.project(TheGame.tmpVec);
TheGame.fontArialM.draw(TheGame.spriteBatch, ply.name, TheGame.tmpVec.x, TheGame.tmpVec.y, 0, Align.center, false);
}
TheGame.spriteBatch.end();
}
This is because if you project something that is behind the camera it still gets valid screen coordinates from the project method.
Consider the following that prints the screen coordinates of two world coordinates
PerspectiveCamera camera = new PerspectiveCamera(60, 800, 600);
camera.position.set(0, 0, -10);
camera.lookAt(0, 0, 0);
camera.update();
Vector3 temp = new Vector3();
Vector3 p1 = new Vector3(1, 0, 10); // This is in front of the camera, slightly to the right
Vector3 p2 = new Vector3(0, 0, -100); // This is behind of the camera
camera.project(temp.set(p1));
System.out.println("p1 is at screen " + temp);
if (camera.frustum.pointInFrustum(p1))
System.out.println("p1 is visible to the camera");
else
System.out.println("p1 is not visible to the camera");
camera.project(temp.set(p2));
System.out.println("p2 is at screen " + temp);
if (camera.frustum.pointInFrustum(p2))
System.out.println("p2 is visible to the camera");
else
System.out.println("p2 is not visible to the camera");
In your code, before rendering the text you need to check if the ply.getPos() vector is visible to the camera, and only render the text if it is.
if (TheGame.cam.frustum.pointInFrustum(ply.getPos()) {
TheGame.tmpVec.set(ply.getPos().x, ply.getPos().y, ply.getPos().z);
TheGame.cam.project(TheGame.tmpVec);
TheGame.fontArialM.draw(TheGame.spriteBatch, ply.name, TheGame.tmpVec.x, TheGame.tmpVec.y, 0, Align.center, false);
}
Note that there are other ways to cull things behind the camera that might be more efficient for you.
Could someone explain the meaning of this value/position: 300-400/2+10. I know it makes that the red circle won't go out of the square but I don't really understand the calculation..? Is there a page where I can read how it works because I personally would do it like this
float redCircle = map(mouseX,0,width,116,485);
circle(redCircle,map(mouseY,0,height,114,485),20);
with one number positions and not a calculation like in the code. I tried to understand it but I don't. I would really appreciate it if someone could explain the proceed.
void setup() {
size(600, 600);
surface.setTitle("Mapping");
surface.setLocation(CENTER, CENTER);
}
void draw() {
background(0);
stroke(255);
fill(255, 255, 255);//weißer Kreis
circle(mouseX, mouseY, 20);
mouseMoved();
text("Maus X/Y:"+mouseX+"/"+mouseY, 250, 300); //Text für weiße Position
fill(255, 0, 0); //Roter Kreis
float posFromMouseX = map(mouseX, 0, width, 300-400/2+10, 300-400/2+400-10);
float posFromMouseY = map(mouseY, 0, height, 300-400/2+10, 300-400/2+400-10);
ellipse(posFromMouseX, posFromMouseY, 20, 20);
text("map to: "+posFromMouseX+" / "+posFromMouseY, 255, 320); //Text für rote Position
// Transparentes Rechteck in der Mitte
noFill();
rect(300-400/2, 300-400/2, 400, 400);
}
map() will adjust the scale of a number accordingly to a range.
For an example, if you have these values:
MouseX: 200
width: 1000
You can easily calculate that, if the screen had a width of 2000 your mouse X position would need to be 400 to be proportional.
But this is an easy example. In the code you pasted here, the same thing is happening, but the coordinates compared are:
The whole window
The white rectangle
The map() function takes 5 args:
map(value, start1, stop1, start2, stop2)
value: float: the incoming value to be converted
start1: float: lower bound of the value's current range
stop1: float: upper bound of the value's current range
start2: float: lower bound of the value's target range
stop2: float: upper bound of the value's target range
So... you can totally write this line without the calculations:
float posFromMouseX = map(mouseX, 0, width, 110, 300-400/2+400-10);
// is the same thing than:
float posFromMouseX = map(mouseX, 0, width, 110, 490);
The probables reasons to write it that way are:
The author may not have wanted to do the simple math
The author may want to know where these numbers come from later (seeing how they were calculated would help on this front)
The author may want to change the hardcoded numbers for variables and make his white rectangle's size dynamic later
Hope it makes sense to you. Have fun!
I am using the p5.js Web Editor
var sketch = function (p) {
with(p) {
p.setup = function() {
createCanvas(400, 400);
secCanvas = createGraphics(400, 400);
secCanvas.clear();
trans = 0;
drop_size = 10;
sun_size = 50;
radius = 10;
};
p.draw = function() {
background(3, 182, 252, 1);
image(secCanvas, 0, 0)
secCanvas.fill(255, 162, 0, 1)
secCanvas.ellipse(width/2, 0 + sun_size, sun_size)
fill(40, trans)
trans = random(255);
ellipse(random(mouseX + radius, mouseX - radius), random(mouseY + radius, mouseY - radius), drop_size)
drop_size = random(50)
};
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
When I set a discrete value of alpha in secCanvas.fill(). The value appears to be gradually increase(and stops soon), while I gave no such instruction. Why is this happening? This only happens when I put background(3, 182, 252, 1); in the draw function but not when I put it in the setup function.
Each frame is drawn on top of all previous frames, so when you draw a semi-transparent background, you can still see the previous frames underneath it.
Think of it as adding a very thin coat of paint over top what you've already painted. Because the color you're adding is semi-transparent, you can still see what's underneath it. Then during the next frame, you add another layer of paint, and the previous frames get just a little more faint.
They stop becoming more faint because of the way the computer calculates the new color, based on the previous frames and the new semi-transparent background color. Long story short, the color you're drawing is almost 100% transparent, so it's not strong enough to completely hide previous frames.
I need to fill a rectangular region with semi-transparent color/brush in mfc. How can I achieve that?
You can't just fill a rectangle with a semi-transparent brush, you'll need to use something like AlphaBlend or TransparentBlt to create the effect.
An example is available here:
http://www.codeproject.com/Articles/286/Using-the-AlphaBlend-function
I found the solution. To fill the rectangle region with semi-transparent brush, we need to use GdiPlus objects.
Here is the Sample Code:
void FillSemiTransparentRegion(CDC *pDC, CRect rc)
{
if (pDC == NULL || rc.IsRectEmpty() || rc.IsRectNull())
return;
Graphics gr(pDC->GetSafeHdc());
SolidBrush br(Color(100, 0, 0, 0)); // Alpha, Red, Blue, Green
gr.FillRectangle(&br, rc.left, rc.right, rc.Width(), rc.Height());
}
I am developing a small game and I would draw a field-ground(land) with a repeated texture. My problem is the rendered result. This gives the impression of seeing everything around my cube looked as if a light shadow.
Is it possible to standardize the light or remove the shadow effect in my drawing function?
Sorry for my bad english..
Here is a screenshot to better understand my problem.
Here my code draw function (instancing model with vertexbuffer)
// Draw Function (instancing model - vertexbuffer)
public void DrawModelHardwareInstancing(Model model,Texture2D texture, Matrix[] modelBones,
Matrix[] instances, Matrix view, Matrix projection)
{
if (instances.Length == 0)
return;
// If we have more instances than room in our vertex buffer, grow it to the neccessary size.
if ((instanceVertexBuffer == null) ||
(instances.Length > instanceVertexBuffer.VertexCount))
{
if (instanceVertexBuffer != null)
instanceVertexBuffer.Dispose();
instanceVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, instanceVertexDeclaration,
instances.Length, BufferUsage.WriteOnly);
}
// Transfer the latest instance transform matrices into the instanceVertexBuffer.
instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
Game.GraphicsDevice.SetVertexBuffers(
new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);
Game.GraphicsDevice.Indices = meshPart.IndexBuffer;
// Set up the instance rendering effect.
Effect effect = meshPart.Effect;
//effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];
effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
effect.Parameters["Texture"].SetValue(texture);
// Draw all the instance copies in a single call.
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
meshPart.NumVertices, meshPart.StartIndex,
meshPart.PrimitiveCount, instances.Length);
}
}
}
}
// ### END FUNCTION DrawModelHardwareInstancing
The problem is the cube mesh you are using. The normals are averaged, but I guess you want them to be orthogonal to the faces of the cubes.
You will have to use a total of 24 vertices (4 for each side) instead of 8 vertices. Each corner will have 3 vertices with the same position but different normals, one for each adjacent face:
If the FBX exporter cannot be configured to correctly export the normals simply create your own cube mesh:
var vertices = new VertexPositionNormalTexture[24];
// Initialize the vertices, set position and texture coordinates
// ...
// Set normals
// front face
vertices[0].Normal = new Vector3(1, 0, 0);
vertices[1].Normal = new Vector3(1, 0, 0);
vertices[2].Normal = new Vector3(1, 0, 0);
vertices[3].Normal = new Vector3(1, 0, 0);
// back face
vertices[4].Normal = new Vector3(-1, 0, 0);
vertices[5].Normal = new Vector3(-1, 0, 0);
vertices[6].Normal = new Vector3(-1, 0, 0);
vertices[7].Normal = new Vector3(-1, 0, 0);
// ...
It looks like you've got improperly calculated / no normals.
Look at this example, specifically part 3.
A normal is a vector that describes the direction that light would reflect off that vertex/poly if shined orthogonally to it.
I like this picture to demonstrate The blue lines are the normal direction at each particular point on the curve.
In XNA, you can calculate the normal of a polygon with vertices vert1,vert2,and vert3 like so:
Vector3 dir = Vector3.Cross(vert2 - vert1, vert3 - vert1);
Vector3 norm = Vector3.Normalize(dir);
In a lot of cases this is done automatically by modelling software so the calculation is unnecessary. You probably do need to perform that calculation if you're creating your cubes in code though.