Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / WPF
Article

ConnectCode Software Box Shot Maker

Rate me:
Please Sign up or sign in to vote.
4.64/5 (6 votes)
26 Mar 2009BSD2 min read 35.7K   585   18   7
An opensource 3D software box shot creator
Click to enlarge image

Introduction

What is a Box Shot

A box shot is a 3D image of a software box. Box shots can help your software sell better. They project a professional image and give your customers an impression of a quality product. A boxshot is a great marketing tool. It encourages visitors on your website to examine your products in more detail. Having one on your website gives you an advantage over your competitors. The reason is simple. The software with a better packaging will stand out from its peers.

ConnectCode Software Box Shot Maker

ConnectCode Software Box Shot Maker is able to create realistic images of 3D software boxes from existing logos and promotional materials. The user simply provides two to three images, adjusts the box orientation and saves the result as an image file.

Supported Features

  • Slider-Based UI For Ease Of Use
  • Rotation of Software Box
  • Adjustments for Camera Distance, Camera Height, Camera Shift from the Software Box
  • Textures for the Front, Top and Side
  • Supports Shadows
  • Box Size

Using the Code

This project is written in .NET 3.0 and utilizes the strengths of WPF 3D. The structure of the software is very simple. A scene is setup consisting of a camera, a rectangular box with six faces and several point lights. Each of the faces of the rectangular software box is painted with images specified as the Front, Side and Top by the user. The Bottom face of the rectangular box is enlarged (scaled by a factor of 4) and used as the ground plane for drawing the shadows.

The visible five faces (excluding the Bottom Face) of the rectangular box are grouped into a single object known as softwareBox. This softwareBox is attached with both a scaling and a rotational Transform so that the box size and the box rotation can be adjusted.

The four methods ResetScene(), CreateGeometries(), PrepareMaterials(), CreateScene() are called in the following order to create the actual image.

C#
private void NewProject()
{
    ResetScene();
    CreateGeometries();
    PrepareMaterials();
    CreateScene();
}
C#
public partial class Window1 : System.Windows.Window
{
        Viewport3D mainViewport = null;
        ModelVisual3D mainMV = null;

        Transform3DGroup boxTr = null;
        Transform3DGroup bottomTr = null;
        Model3DGroup scene = null;
        Model3DGroup softwareBox = null;
        PerspectiveCamera sceneCamera = null;
        PointLight ptLight1 = null;
        PointLight ptLight2 = null;
        PointLight ptLight3 = null;
        PointLight ptLight4 = null;

        GeometryModel3D SecondSideFace = null;
        GeometryModel3D SideFace = null;
        GeometryModel3D BottomFace = null;
        GeometryModel3D FrontFace = null;
        GeometryModel3D TopFace = null;
        GeometryModel3D SecondFrontFace = null;

        public ImageSource imgFrontSrc = null;
        public ImageSource imgSideSrc = null;
        public ImageSource imgTopSrc = null;
        public ImageSource imgBottomSrc = null;
        ImageBrush imgFrontBrush = null;
        ImageBrush imgSideBrush = null;
        ImageBrush imgTopBrush = null;
        ImageBrush imgBottomBrush = null;

        String startfolder = "";
        Window3 PropDlg = null;

        //Main Parameters
        public Double angleOfRotation;
        public Double viewDistance;
        public Double viewHorizontalShift;
        public Double viewHeight;

        public Double scaleX;
        public Double scaleY;
        public Double scaleZ;

        public String imgFront;
        public String imgSide;
        public String imgTop;
        public String imgBottom;

        public Double ptLight1PosX;
        public Double ptLight1PosY;
        public Double ptLight1PosZ;

        public Double ptLight2PosX;
        public Double ptLight2PosY;
        public Double ptLight2PosZ;

        public Double ptLight3PosX;
        public Double ptLight3PosY;
        public Double ptLight3PosZ;

        public Double ptLight4PosX;
        public Double ptLight4PosY;
        public Double ptLight4PosZ;

        public Double ptLight1Att;
        public Double ptLight2Att;
        public Double ptLight3Att;
        public Double ptLight4Att;

        public Boolean includeShadows;

        public int ImgWidth = 400;
        public int ImgHeight = 400;

        public void ResetScene()
        {
            angleOfRotation = 19;
            viewDistance = 6;
            viewHorizontalShift = 1;
            viewHeight = 0.2;

            scaleX = 0.5;
            scaleY = 1.5;
            scaleZ = 1.2;

            imgFront = "";
            imgSide = "";
            imgTop = "";
            imgBottom = "";

            ptLight1PosX = 3;
            ptLight1PosY = 0.7;
            ptLight1PosZ = -1;
            ptLight1Att = 0.02;

            ptLight2PosX = 3;
            ptLight2PosY = 0.7;
            ptLight2PosZ = 3;
            ptLight2Att = 0.01;

            ptLight3PosX = 0;
            ptLight3PosY = 7;
            ptLight3PosZ = 0;
            ptLight3Att = 0.02;

            ptLight4PosX = 0;
            ptLight4PosY = 2;
            ptLight4PosZ = 0;
            ptLight4Att = 0.000002;

            includeShadows = true;
        }

        private void CreateGeometries()
        {
            SecondSideFace = new GeometryModel3D();
            SideFace = new GeometryModel3D();
            BottomFace = new GeometryModel3D();
            FrontFace = new GeometryModel3D();
            TopFace = new GeometryModel3D();
            SecondFrontFace = new GeometryModel3D();

            SideFace.Geometry = 
		(MeshGeometry3D)Application.Current.Resources["SideFace"];
            SecondFrontFace.Geometry = 
		(MeshGeometry3D)Application.Current.Resources["SecondFrontFace"];
            SecondSideFace.Geometry = 
		(MeshGeometry3D)Application.Current.Resources["SecondSideFace"];
            BottomFace.Geometry = 
		(MeshGeometry3D)Application.Current.Resources["BottomFace"];
            FrontFace.Geometry = 
		(MeshGeometry3D)Application.Current.Resources["FrontFace"];
            TopFace.Geometry = (MeshGeometry3D)Application.Current.Resources["TopFace"];

            softwareBox = new Model3DGroup();
            softwareBox.Children.Add(SecondSideFace);
            softwareBox.Children.Add(SideFace);
            //softwareBox.Children.Add(BottomFace);
            softwareBox.Children.Add(FrontFace);
            softwareBox.Children.Add(TopFace);
            softwareBox.Children.Add(SecondFrontFace);
        }

        public void PrepareMaterials()
        {
            UpdateImageSource();

            imgFrontBrush = new ImageBrush();
            imgSideBrush = new ImageBrush();
            imgTopBrush = new ImageBrush();
            imgBottomBrush = new ImageBrush();

            imgFrontBrush.ImageSource = imgFrontSrc;
            imgSideBrush.ImageSource = imgSideSrc;
            imgTopBrush.ImageSource = imgTopSrc;
            imgBottomBrush.ImageSource = imgBottomSrc;

            DiffuseMaterial FrontFaceMaterial = 
			new DiffuseMaterial((Brush)imgFrontBrush); //front
            DiffuseMaterial SecondFrontFaceMaterial = 
			new DiffuseMaterial((Brush)imgFrontBrush); //front2
            DiffuseMaterial TopFaceMaterial = 
			new DiffuseMaterial((Brush)imgTopBrush); //top
            DiffuseMaterial BottomFaceMaterial = 
			new DiffuseMaterial((Brush)imgBottomBrush); //bottom
            DiffuseMaterial SecondSideFaceMaterial = 
			new DiffuseMaterial((Brush)imgSideBrush); //side2
            DiffuseMaterial SideFaceMaterial = 
			new DiffuseMaterial((Brush)imgSideBrush); //side
            //SpecularMaterial BottomFaceMaterial = 
			new SpecularMaterial((Brush)imgBottomBrush, 0.3);
            //EmissiveMaterial BottomFaceEmmisiveMaterial = 
			new EmissiveMaterial((Brush)imgBottomBrush); //bottom

            FrontFace.Material = FrontFaceMaterial;
            SecondFrontFace.Material = SecondFrontFaceMaterial;
            SideFace.Material = SideFaceMaterial;
            SecondSideFace.Material = SecondSideFaceMaterial;
            TopFace.Material = TopFaceMaterial;
            BottomFace.Material = BottomFaceMaterial;
            //BottomFace.Material = BottomFaceEmmisiveMaterial;
        }

        public void UpdateImageSource()
        {
            //Get Textures
            if (imgFront == "")
                imgFront = startfolder + "\\front.jpg";

            if (imgSide == "")
                imgSide = startfolder + "\\side.jpg";

            if (imgTop == "")
                imgTop = startfolder + "\\top.jpg";

            if (imgBottom == "")
                imgBottom = startfolder + "\\shadow.jpg";

            imgFrontSrc = RetreiveImageSource(imgFront);
            imgSideSrc = RetreiveImageSource(imgSide);
            imgTopSrc = RetreiveImageSource(imgTop);
            imgBottomSrc = RetreiveImageSource(imgBottom);
        }

        private void CreateScene()
        {
            mainViewport = new Viewport3D();

            RotateTransform3D rTr = new RotateTransform3D
		(new AxisAngleRotation3D(new Vector3D(0, 1, 0), angleOfRotation));
            ScaleTransform3D sTr = new ScaleTransform3D(scaleX, scaleY, scaleZ);
            ScaleTransform3D bsTr = new ScaleTransform3D(4, scaleY, 4);

            sceneCamera = new PerspectiveCamera();
            sceneCamera.FieldOfView = 45;
            sceneCamera.Position = 
		new Point3D(viewDistance, viewHeight, viewHorizontalShift);
            sceneCamera.UpDirection = new Vector3D(0, 1, 0);
            sceneCamera.LookDirection = 
		new Vector3D(-viewDistance, -viewHeight, -viewHorizontalShift);
            mainViewport.Camera = sceneCamera;

            boxTr = new Transform3DGroup();
            bottomTr = new Transform3DGroup();
            bottomTr.Children.Add(bsTr);
            bottomTr.Children.Add(rTr);

            boxTr.Children.Add(sTr);
            boxTr.Children.Add(rTr);

            softwareBox.Transform = boxTr;
            BottomFace.Transform = bottomTr;

            ptLight1 = new PointLight();
            ptLight2 = new PointLight();
            ptLight3 = new PointLight();
            ptLight4 = new PointLight();
            ptLight1.Position = 
		new Point3D(viewDistance-3, viewHeight+0.5, viewHorizontalShift-2);
            ptLight2.Position = 
		new Point3D(viewDistance-3, viewHeight+0.5, viewHorizontalShift+2);
            ptLight1.Position = new Point3D(ptLight1PosX, ptLight1PosY, ptLight1PosZ);
            ptLight2.Position = new Point3D(ptLight2PosX, ptLight2PosY, ptLight2PosZ);
            ptLight3.Position = new Point3D(ptLight3PosX, ptLight3PosY, ptLight3PosZ);
            ptLight4.Position = new Point3D(ptLight4PosX, ptLight4PosY, ptLight4PosZ);
            ptLight1.Color = Colors.White;
            ptLight2.Color = Colors.White;
            ptLight3.Color = Colors.White;
            ptLight4.Color = Colors.White;
            ptLight1.QuadraticAttenuation = ptLight1Att;
            ptLight2.QuadraticAttenuation = ptLight2Att;
            ptLight3.QuadraticAttenuation = ptLight3Att;
            ptLight4.QuadraticAttenuation = ptLight4Att;

            scene = new Model3DGroup();
            scene.Children.Add(softwareBox);
            scene.Children.Add(ptLight1);
            scene.Children.Add(ptLight2);
            scene.Children.Add(ptLight3);
            scene.Children.Add(ptLight4);

            if (includeShadows)
            {
                scene.Children.Add(BottomFace);
            }

            mainMV = new ModelVisual3D();
            mainMV.Content = scene;
            mainViewport.Children.Add(mainMV);

            workPanel.Children.Add(mainViewport);
        }
}

This tool gives anyone interested in writing or extending a box shot making software an opportunity to create their own custom box shots software using more advanced algorithms. For example, users can edit their own shadow image to produce better looking shadows. Otherwise, they can use other Material such as EmmisiveMaterial or SpecularMaterial to make the box more realistic.

Original Website

For updates and more information on ConnectCode Software Box Shot Maker, please visit the original site for this project: Box Shot.

History

  • 26th March, 2009: Initial version

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Singapore Singapore
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralText Pin
Dmitri Nеstеruk28-Mar-09 10:56
Dmitri Nеstеruk28-Mar-09 10:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.