|
Oh for goodness sake ... I've gone and made an arse of myself in public AGAIN!
I really shouldn't be trying new things on a Sunday afternoon after a large meal and a few pints ... all the blood is in my stomach!
Jammer
Going where everyone here has gone before!
My Blog
|
|
|
|
|
Hello people!
I am a bit new to WPF (worked with WinForms till now). What am I trying to do is a sort of texture mapping.
When I was warking with WinForms I was using Directx SDK.
In my program I am getting a byte array that represents pixels in RGB format. for example byte[] arr = {r1,b1,g1,r2,b2,g2...rn,bn,gn};
So each 3 array cells represent one pixel. Then I was creating a MemoryStream. I had pre-written BMP file header, so I just write my header into the stream and then write my array there as well. So now I've got a Stream that represents a BMP image.
Now I've got my image in the stream. Then, in WinForms+ DirectX SDK I was creating a triangle primitive and was drawing my BMP image on this primitive ( texture mapping);
Now I want to do the same thing in WPF. I still have my byte[] arr ;
Here is the code of what I've done:
First of all this is my "Primitive class"
class PpiSegment : ModelVisual3D
{
MeshGeometry3D segmentMesh;
DiffuseMaterial segmentMaterial;
BitmapImage segmentTexture;
ImageSource segmentTextureSource;
ImageBrush segmentBrush;
// I get 3 points coordinates in the Constructor
public Segment(Point3D leftPoint, Point3D rightPoint, Point3D middlePoint)
{
segmentMesh = new MeshGeometry3D();
segmentMaterial = new DiffuseMaterial();
segmentTexture = new BitmapImage();
segmentBrush = new ImageBrush();
this.Content = new GeometryModel3D();
(this.Content as GeometryModel3D).Geometry = CreateTriangleCoords(leftPoint, rightPoint, middlePoint);
}
/* middle(center)
* /\
* / \
* / \
* / \
* left -------- right
*
*/
internal Geometry3D CreateTriangleCoords(Point3D leftPoint, Point3D rightPoint, Point3D middlePoint)
{
segmentMesh.Positions.Add(leftPoint);
segmentMesh.Normals.Add((Vector3D)leftPoint);
segmentMesh.TextureCoordinates.Add(new Point(1.0, 1.0));
segmentMesh.Positions.Add(rightPoint);
segmentMesh.Normals.Add((Vector3D)rightPoint);
segmentMesh.TextureCoordinates.Add(new Point(1.0, 1.0));
segmentMesh.Positions.Add(middlePoint);
segmentMesh.Normals.Add((Vector3D)middlePoint);
segmentMesh.TextureCoordinates.Add(new Point(0.0, 0.0));
segmentMesh.TriangleIndices.Add(2);
segmentMesh.TriangleIndices.Add(1);
segmentMesh.TriangleIndices.Add(0);
segmentMesh.Freeze();
return segmentMesh;
}
-----------------------------------------------------------------------------------------------------------
and now to the interresting part:
Here I am giving a BMP stream as an Image for the Brush.
//This Stream WAS INITIALIZED Before.
public Stream bitmapStream = new MemoryStream();
//On the first run of my class I call for this function to initialize the "StreamSource" parameter of
"segmentTexture"
public void SetTexture()
{
segmentTexture.BeginInit();
segmentTexture.StreamSource = bitmapStream;
segmentTexture.EndInit();
segmentTextureSource = segmentTexture;
segmentBrush.ImageSource = segmentTextureSource;
segmentMaterial.Brush = segmentBrush;
(this.Content as GeometryModel3D).Material = segmentMaterial;
this.Transform = new TranslateTransform3D(0.0, 0.0, 0.0);
}
Ok, I've got my image loaded. BUT! Now I need to change the image!
So I create somewhere a NEW stream and I amtrying to pass it like I did it before..
public void SetNewTexture(Stream newStream)
{
//I dont need Init/EndInit functions any more... (Don't I?)
segmentTexture.StreamSource = newStream;
segmentTextureSource = segmentTexture;
segmentBrush.ImageSource = segmentTextureSource;
segmentMaterial.Brush = segmentBrush;
(this.Content as GeometryModel3D).Material = segmentMaterial;
this.Transform = new TranslateTransform3D(0.0, 0.0, 0.0);
}
}
But! When I do that NOTHING happens... Image on my triangle primitive doesnt change...
-------------------------------------------------------------------------------------------------------------------------------
Here How I use my Segment class.. maybe its the problem....
class SegmentsBuilder
{
private ModelVisual3D _mv3D;
public PpiSegment[] segmentsArray;
//I am getting a "modelVisual3D" parameter from Window1.xaml
public SegmentsBuilder(ModelVisual3D modelVisual3D)
{
_mv3D = modelVisual3D;
segmentsArray = new PpiSegment[General.numberOfSegments];
}
//I am creating a circle from some number of triangles with textures on them
public void BuildSegments()
{
Point3D leftPoint, rightPoint, middlePoint;
double theta = MathHelper.DegToRad(360.0 / General.numberOfSegments);
double R = 0.95;
middlePoint = new Point3D(0.0, 0.0, General.ppiZCoordinate);
// create a list of triangles
for (int i = 0; i < General.numberOfBeems; i++)
{
//left
leftPoint = new Point3D();
leftPoint.X = R * Math.Cos((double)(i + 1) * theta);
leftPoint.Y = R * Math.Sin((double)(i + 1) * theta);
leftPoint.Z = General.ppiZCoordinate;
//right
rightPoint = new Point3D();
rightPoint.X = R * Math.Cos((double)(i) * theta);
rightPoint.Y = R * Math.Sin((double)(i) * theta);
rightPoint.Z = General.ppiZCoordinate;
segmentsArray[i] = new PpiSegment(rightPoint,leftPoint, middlePoint);
_mv3D.Children.Add(segmentsArray[i]);
}
}
public void UpdateTexture(int segment, Stream texture)
{
segmentsArray[segment].SetNewTexture(texture);
}
So here are my questions...
1)What do I do wrong? Why nothing happens over there?...
2)As I said before I am WPF noobie, so maybe there is another way of doing texture mapping, or doing my task (drawing a bitmap on the triangle)
Any help/ideas/opinions are really welcome... :]
|
|
|
|
|
Am I right in understanding that the bitmap was visible but did not change when you updated the bitmap?
I tried using a MemoryStream and only got it to change by recreating the BitmapDecoder and setting the ImageSource each time, even though it was set not to cache the result.
I also tried using WriteableBitmap in that case just changing the ImageSource on the ImageBrush was enough for it to update. The WriteableBitmap class is improved in 3.5 sp1 and allows access via pointers (don't for get to use AddDirtRect). You can also just write the whole array if you want.
If your not not updating the bitmap I may have misunderstood, if it doesn't show up at all I would check the texture coordinates and test by setting the BackMaterial to a SolidColor. You may also want to check if any of the materials, images e.t.c are Frozen.
|
|
|
|
|
thank you very much! You did understand me right, it just wasnt updating The WriteableBitmap is the solution ;]
|
|
|
|
|
Hi all,
I m new to WPF. I m developing one application in which i want to read XAML file and iterate thru each control element and find the name and value of that control and write to another xml file.
So kindly need yr suggesion..
Thanks
Krishnraj
|
|
|
|
|
the class XamlReader let's you read the root element from a xaml file (with Read method)
then you could iterate thru the logical tree using LogicalTreeHelper
Good Luck
|
|
|
|
|
Hi yanairon,
Thank u very much for replying
OK Now i got the idea.
Again Thanks
Rana Krishnraj
|
|
|
|
|
Hello,
I would like to set the object as a startup object in WPF. Normally, we used to use "this.StartupUri" for that. but I have to use the Uri of XAML file here. I don't like that. I want to set like this.Startup = new MyView(); in App.
Any idea?
Thanks in advance.
Edit: My WPF project should be XBAP-compatible. So, I can't use "Show()" or "Run()" method....
|
|
|
|
|
Michael Sync wrote: this.Startup = new MyView(); in App
Would the Application.MainWindow property work for you?
Why is common sense not common?
Never argue with an idiot. They will drag you down to their level where they are an expert.
Sometimes it takes a lot of work to be lazy
Individuality is fine, as long as we do it together - F. Burns
|
|
|
|
|
Wes Aday wrote: Would the Application.MainWindow property work for you?
I just tried but not working. It doesn't show anything on the screen unless we call "Show". But I can't use it "Window" class in Xbap..
I'm not sure why we don't have this.Startup or this.StartUpObject even we have this.StartupUri.
|
|
|
|
|
Hi Michael,
You would need to modify app.g.i.cs file.
Then find StartupURI property of application and modify as:
this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);
Hope this helps.
Vinay
ComponentOne LLC.
www.componentone.com
|
|
|
|
|
Vinay Srivastava wrote: this.StartupUri = new System.Uri("Window1.xaml", System.UriKind.Relative);
Actually, we would like to use with Unity framework.. I have successfully ported Unity framework for Silverlight.. I want to use the code below at that startup..
this.Startup = container.Resolve<shell>();
How can I do that?
In Silverlight, we can do like that..
private void Application_Startup(object sender, StartupEventArgs e) {
IUnityContainer container = new UnityContainer()
.RegisterType<ILogger, TraceLogger>()
.RegisterType<IStoplightTimer, RealTimeTimer>();
this.RootVisual = (UIElement)container.Resolve<StoplightView>();
}
Ref: http://michaelsync.net/2008/07/11/unity-application-block-unity-for-silverlight-and-stoplight-quickstart[^]
|
|
|
|
|
Hello friends...
i have a listview filled with data in it .
and i have a textbox with some string in it.
how can i find that string in the listview and color that particular cell.
can you help me out..
cheers
chandu
|
|
|
|
|
You could try binding the background brush to the textbox and use a custom converter that receives as a parameter the string from the cell.
Mihai,
|
|
|
|
|
|
Good afternoon colleagues:
I have a tricky question, on which even Microsoft's evangelist could not provide a clear solution.
I want to compare performance of WinForms and WPF rendering models.
For that purpose I measure time span between content update event and rendered event.
In WinfForms the operation is very straight forward, cause there is an OnPaint event. But in WPF I cannot find an analog of this event.
Certainly, the rendering model in WPF is totally different, thus refresh of the data is performed somehow in another way.
So, to be more precise, I want to know when actually the content appears on the screen.
I have conducted some research and there is seems to be a Load event, which serves for this purpose, but this event is fired only once on application start up.
Perforator somehow measures rendering time. But it doesn't use WPF for that purpose, but WinAPI.
Thanks!
/LOOM
|
|
|
|
|
|
Hi Mark!
I have already seen this document. Probably, need to address it again.
BTW, on the Microsoft's forum I was recommended to use RenderSizeChanged event. Will try it an get back later.
Thanks!
/LOOM
|
|
|
|
|
Hi again!
I created an UserControl which is a singleton.
public partial class DeepDisplay : UserControl
{
private static DeepDisplay instance;
private static object lockObject = new object();
private DeepDisplay()
{
InitializeComponent();
}
public static DeepDisplay GetInstance()
{
lock (lockObject)
{
if (instance == null)
instance = new DeepDisplay();
}
return instance;
}
}
What I want to do is to add this UserControl in the XAML Part of the code.
<local:DeepDisplay x:Name="deepDisplay" Width="Auto"></local:DeepDisplay>
Due to the fact that the Constructor is private, I need to call the GetInstance Method instead.
Can this be done easily and if so, can someone be so kind a show me how?
As always thank you in advance,
eza
|
|
|
|
|
I'm quite sure that is impossible.
Anyway, a singleton control sounds like a very bad idea. First of all why would you need such a thing? Seccondly, how would you expect it to work when you add a seccond "instance" of the control? I'm asking this because a control can only have one parent, so it can't be in to places at once.
On the other side, if you want to make sure that the control is only used once, you could keep track of the number of instances created in a static variable, and throw an error when another instance has already been created.
Mihai,
|
|
|
|
|
hi,
I have a result set form the database stored in the ILIST. I want to bind this to a listview[in which i use grid view]. Does any one have a solution for this ..if, plz help me
|
|
|
|
|
|
Hi All,
I feel like I should know the answer to this by now but I'm stuck.
I have a number of combo boxes in the UI, the contents of one is dynamic based on the selected item of another. All the comboboxes are bound to OberservableCollections created in a static ComboBoxManager class.
Whats the best way of handling the selection changing in the first combobox in order to populate the second combobox with the correct contents?
How do I get this selection changed event into this other class? Do I have to register a custom event in the ComboBoxManager class? Or can I create a 'Selection' property on the ComboBoxManager class and bind the first comboboxes selected item to it in a two way binding to this property and add a handler to this property to kick off some code when it changes?
Or is this all a bit overkill and I just need to use a RoutedEvent listener in the ComboBoxManager class??
Jammer
Going where everyone here has gone before!
My Blog
|
|
|
|
|
Hi All,
I've just created a small expample solution showing what I'm trying to do. I want to keep all the code out of the Window1 class basically whilst pointing the comboboxes to the event hander in the ComboBoxManager class. You can get the solution here:
EventRouting.zip[^]
Any input on this would be really appricated.
Jammer
Going where everyone here has gone before!
My Blog
|
|
|
|
|
Jammer mate. The answer to your problems is here[^].
|
|
|
|