If I understood the Mathematica documentation correct ( haven't found examples either ) Graphics3D does not produce shadows of 3D objects, although Graphics3D has a Lighting-> option.
Question: Have you ever tried to produce Mathematica 3D objects with shadows? If so have you solved this in Mathematica? Or have you exported the graphics to other 3D ( scene-graph ) viewers like for example J-Reality?
The shading model used by MMA, the so-called Phong shading, determines the pixel intensities based on a simple relationship between local surface orientation, light source direction(s), camera direction and diffuse and specular properties of the surface. No other aspect of the geometry is taken into account, which means that objects do not influence the pixel values of other objects even if they are between the object and the light source.
This means that the model doesn't generates shadows. It is not able to.
You could simulate shadows yourself by projecting your object's polygons on the ground plane or wall planes as applicable. That shouldn't be too difficult, but shadows on non-planar surfaces will be pretty hard.
Example:
polys = (PolyhedronData["GreatRhombicTriacontahedron", "Faces"] //
Normal // N) /. {x_, y_, z_}?VectorQ -> {x, y, z + 6};
(* raise it slightly above ground plane*)
shadow = polys /. {x_, y_, z_}?VectorQ -> {x - z, y, 0};
(* projection from a directional light source at 45 deg elevation *)
Graphics3D[{polys, EdgeForm[], FaceForm[Darker#Gray], shadow},
Lighting -> {{"Directional", White, {{1, 0, 1}, {0, 0, 0}}}},
Boxed -> False]
Of course, you need to make sure that the lighting sources (point, spot, directional...) and your shadow projection are consistent.
Related
I have a stationary camera, which is 640mm above the ground and is tilted slightly forward (about the x-axis?) roughly 30 degrees, so it's looking slightly down towards a flat ground plane.
My goal is to determine the distance from the camera to any small objects that it detects on the ground, for example, if my camera detects an object which is located at pixel [314, 203], I would like to know where on the ground that object would be in world coordinates [x, y, z] with y=0, and the distance to that object.
I've drawn a diagram to better visualize the problem:
camera plane diagram
I have my rotation matrix and translation vector and also my intrinsic matrix, but I'm not sure 1) if the rotation matrix and translation vector are correct given the information/diagram above, and 2) how to proceed with figuring out a mathematical formula for finding distance and real world location. Here is what I have so far:
Rotation matrix R (generated here https://www.andre-gaschler.com/rotationconverter/) from the orientation [-30, 0, 0] (degrees)
R =
[ 1.0000000, 0.0000000, 0.0000000;
0.0000000, 0.8660254, -0.5000000;
0.0000000, 0.5000000, 0.8660254 ]
Camera is 640mm above ground plane
t =
[0, 640, 0]
Intrinsic matrix from calibration information given by camera
fx=349.595, fy=349.505, cx=328.875, cy=178.204
K =
[ 349.595, 0.0000, 328.875;
0.0000, 349.505, 178.204;
0.0000, 0.0000, 1.000 ]
I also have these distortion parameters, I'm unsure what to do with them or if they are relevant to K
k1=-0.170901, k2=0.0255027, k3=-9.30328e-11, p1=0.000117187, p2=6.42836e-05
I get about this far and then I'm lost, any help would be much appreciated.
Also sorry if this is a lot of information or if it's confusing in any way, I'm very much a beginner when it comes to projection matrices
UPDATE:
After some more research and testing on my own I found a formula that seems to give me a somewhat decent approximation. Given pixel [x, y], I find (I think) the direction vector from the camera origin to the pixel coordinate with:
dir_x = (x - cx) / fx
dir_y = (y - cy) / fy
dir_z = 1
which I then multiply by rotation matrix R, which gives me the real-world vector. I then divide my camera height (640mm) by the y-value of that vector, which gives me (I think) the distance to the specified pixel in the real-world. After some testing and measuring by hand, this seems to be an adequate method for finding the distance, but I'm not sure if I'm missing steps for accuracy or if I'm actually doing this completely wrong.
Again, any insight is greatly appreciated.
I need to generate a bicubic ellipsoid, for which I've tried to set up the parametric equation of an ellipsoid in mathematica like
ParametricPlot3D[{4 Sin[u] Cos[v], 3 Sin[u] Sin[v], 2 Cos[u]}, {u, 0,
Pi}, {v, 0, 2 Pi}, Mesh -> False, Background -> Black,
Boxed -> False, Axes -> False]
My problem is that since I need a bicubic surface, I want to limit this parametric plot to 16 points and I cant figure out how to make mathematica sample only the number of points I need.I'm a newbie to both mathematica and geometric modeling.
This question might seem a little strange but for my purposes is not that crazy.
Its easy but I need you to follow me.
The aim
My aim is plotting a tridimensional graph.
The problem
The problem is the material I have in my hands to start building this graph. Actually I have a collection of points in the 2D space (thus tuples of two real ordered values). Consider a moment to have these collection of points stored into an array and now consider to plot them on a 2D diagram. You will just have a nice sparse view of these points.
Well, the second step is this: consider the surface with these points and create a third axis orthogonal to the plane where those points are drawn. The aim is assigning to every point a numerical scalar value (using a function that accepts the couple and returns a numerical value). So the graph should show bars starting from every point and having a specific value according to the assignment function.
How can I achieve this in Mathematica?
A little note
Basically my points in the 2d space are also connected by a graph. Is it possible to connect the top of the bars to the top of other bars whose base point are connected together in the 2d graph?
Some other notes
My graph doesn`t have to be a surface but just a collection of bars placed on a plane in the exact place where the correspondent point they refer to is located. But if you have a good hint how to draw a surface other than bars, it will be gladly accepted.
I hope I was clear. I would like to point that I have Mathematica 8 so all functionalities are available. Thank you.
This can be done using Graphics3D primitives. Lets start with some data
(* a list of 2D coordinates *)
points2D = RandomReal[{0, Pi}, {50, 2}];
(* some edges as a list of pairs of vertex indices *)
edges = Union[Flatten[MapIndexed[Sort /# Thread[{#2[[1]],
Nearest[points2D -> Automatic, #, 4]}] &, points2D], 1]];
(* constructing list of 3D coordinates *)
f[{x_, y_}] := 2 + Sin[x y]
points3D = {##, f[{##}]} & ### points2D;
The actual plot can then be constructed as follows (width is half the width of the bars)
With[{width = .02},
Graphics3D[{{LightBlue, EdgeForm[None],
Cuboid[{#1, #2, 0} - width {1, 1, 0}, {##} + width {1, 1, 0}] & ### points3D},
{Orange,
GraphicsComplex[points3D, Line[edges]]}},
Lighting -> "Neutral",
BoxRatios -> {1, 1, .6}]]
Continuing with the project I previously described I am currently building an animation showing movement between a list of cities. My current code renders a list of cities and makes a set of great circle arcs connecting the cities. The list of cities are part of a timeline so after visiting one city the animation will transition to be centered upon the next.
To my mind this means the ViewVector should be adjusted to show points between a starting city and an ending city. The resulting would probably look like an in-flight map for a long-haul flight sped up considerably. A single frame might look like the following manually produced still:
I now understand how to position the ViewVector above the most recent city but I am quite unsure about how to move the camera smoothly between two spherical coordinate points. My current code is below:
SC[{lat_, lon_}] := {Cos[lon \[Degree]] Cos[lat \[Degree]],
Sin[lon \[Degree]] Cos[lat \[Degree]], Sin[lat \[Degree]]};
GreatCircleArc[{lat1_, lon1_}, {lat2_, lon2_}] :=
Module[{u = SC[{lat1, lon1}], v = SC[{lat2, lon2}], a},
a = VectorAngle[u, v];
Table[Evaluate[RotationTransform[\[Theta], {u, v}][u]], {\[Theta],
0, a, a/Ceiling[10 a]}]]
CityGraphic[name_] := {Opacity[0.85], Black, PointSize[Medium], White,
PointSize[0.045], Point[1.01 SC[CityData[name, "Coordinates"]]]}
CityGraph[places_, age_] :=
Graphics3D[{
Opacity[0.75],
Sphere[{0, 0, 0}, 0.99 ],
Map[Line[
Map[SC,
CountryData[#, "SchematicCoordinates"], {-2}]] &,
CountryData["Countries"]],
Map[CityGraphic, places],
Text[Style[age, FontFamily -> "Helvetica"],
1.02 SC[CityData[First[places], "Coordinates"]]],
White, Line
[Apply[GreatCircleArc,
Partition[Map[CityData[#, "Coordinates"] &, places], 2, 1], {1}]]
},
ViewVector -> {
4 SC[CityData[First[places], "Coordinates"]], {0, 0, 0}},
Boxed -> False,
SphericalRegion -> True,
ImageSize -> {640, 480}
];
CityGraph[{"Tokyo", "Dublin", "Cape Town", "Seattle", "Denver"}, "04"]
In computer graphics people often use Quaternions to smoothly interpolate between various camera viewing directions. Mathematica has a Quaternion package which you could use for basic Quaternion arithmetic. A conversion between Quaternions and Euler angles is described here.
The interpolation process is described here.
As a little project I've been thinking to create a little Google Earth-like animation. I want to play back a timeline while rotating the globe to center over various cities. At present I can use the default view settings to render a globe with the cities indicated by points.
When I try to orient the camera with a view vector looking down on a city (for example Denver), I end up with the following:
The ViewVector needs to be computed for some point out in space above the globe. However my trial and error has not arrived on any sort of coherent viewpoint with most looking like they're "inside" the globe.
What I need help with is a function which given the latitude and longitude of a city choses a ViewVector placing the city at the "center" of the camera view. The code which produced the "inside the globe" view follows:
SC[{lat_, lon_}] := {Cos[lon \[Degree]] Cos[lat \[Degree]],
Sin[lon \[Degree]] Cos[lat \[Degree]], Sin[lat \[Degree]]};
Graphics3D[{
Opacity[0.75],
Sphere[{0, 0, 0}, 0.99 ],
Map[Line[
Map[SC,
CountryData[#, "SchematicCoordinates"], {-2}]] &,
CountryData["Countries"]], {Yellow, PointSize[Medium],
Point[SC[CityData["Denver", "Coordinates"]]]
}
},
Boxed -> False,
SphericalRegion -> True,
ViewVector -> {{0, 0, 0}, SC[CityData["Denver", "Coordinates"]]}
]
When using ViewVector in the form ViewVector->{v1, v2}, the camera is sitting in point v1 and is pointed in the direction of v2. So in your example, the camera would be sitting in the origin and is pointed in the direction of Denver, which produces the "inside globe" view. To have the camera looking down at Denver the camera should be sitting in a point directly above the city, e.g. in 2 SC[CityData["Denver", "Coordinates"] and be pointed at the origin, so ViewVector would be something like
ViewVector -> {2 SC[CityData["Denver", "Coordinates"]], {0, 0, 0}}
With this setting for ViewVector the view becomes something like