Beispiel #1
0
        private string GetTexture(BaseContainer data, BaseChannel matChannel)
        {
            string resultName = null;
            string texture    = data.GetString(C4dApi.BASECHANNEL_TEXTURE);

            if (!string.IsNullOrEmpty(texture))
            {
                texture    = Path.GetFileNameWithoutExtension(texture);
                texture   += ".jpg";
                resultName = texture;

                if (!_textureFiles.Contains(texture))
                {
                    matChannel.InitTexture(new InitRenderStruct(_doc));
                    using (BaseBitmap bitmap = matChannel.GetBitmap())
                    {
                        if (bitmap != null)
                        {
                            using (BaseContainer compressionContainer = new BaseContainer(C4dApi.JPGSAVER_QUALITY))
                            {
                                bool bRet = bitmap.SetColorProfile(ColorProfile.GetDefaultSRGB());
                                compressionContainer.SetFloat(C4dApi.JPGSAVER_QUALITY, 70.0);
                                string textureFileAbs = Path.Combine(_sceneRootDir, texture);
                                bitmap.Save(new Filename(textureFileAbs), C4dApi.FILTER_JPG, compressionContainer,
                                            SAVEBIT.SAVEBIT_0);
                                _textureFiles.Add(texture);
                            }
                        }
                        else
                        {
                            resultName = null;
                        }
                    }
                    matChannel.FreeTexture();
                }
            }
            return(resultName);
        }
        // Different ways how data (The...) is obtained and written.
        // Example 1: An override gets the baseTag/BaseObject:
        //
        // Working example from DoubleCircle:
        // public override retval OverrideMethod(..., BaseTag tag, ...)
        // {
        //    BaseContainer di = tag.GetDataInstance();                       // Get the data instance from the object
        //    int theIntContents = di.GetInt(GENERAL_TAG_THEINT);             // Retrieve the data from the data instance

        //  Question: Would it be sufficient to simply use this.GetDataInstance()



        public override bool GetDDescription(GeListNode node, DDescriptionParams descparams)
        {
            // The main part of this code is taken from the "LookAtCamera.cpp" file from the original C4D API samples.

            // TODO: whatever this might be good for: if (!singleid || cid.IsPartOf(*singleid, NULL)) // important to check for speedup c4d!
            // {
            if (!descparams.Desc.LoadDescription("tbase"))
            {
                return(false);
            }


            // According to https://developers.maxon.net/docs/Cinema4DCPPSDK/html/class_description.html and
            // with #define DESCID_ROOT DescID(DescLevel(1000491, 0, 0)) as set in lib_description.h
            // Set the tag's name to something meaningful (other than "Base Tag" or "Basis Tag"
            DescID        nCid    = new DescID(new DescLevel(1000491, 0, 0));                    // The ID of the radius value (GENERAL_TAG_THEINT)
            BaseContainer nBc     = descparams.Desc.GetParameterI(nCid, null);                   // The type of the radius value (LONG)
            string        OldName = nBc.GetString(C4dApi.DESC_NAME);

            nBc.SetString(C4dApi.DESC_NAME, TagName);



            //////////////////////////////////////////////////////////////////////////////////////
            // Create an int value named TheInt on the "Base" tab's main level
            DescID        cid = new DescID(new DescLevel(GENERAL_TAG_THEINT, C4dApi.DTYPE_LONG, 0)); // The ID of the radius value (GENERAL_TAG_THEINT)
            BaseContainer bc  = C4dApi.GetCustomDataTypeDefault(C4dApi.DTYPE_LONG);                  // The type of the radius value (LONG)

            bc.SetString(C4dApi.DESC_NAME, "TheInt");                                                // The user interface name (TheInt)
            bc.SetInt32(C4dApi.DESC_DEFAULT, 44);                                                    // The default value (44, but overridden to 42 in the Init method)
            if (!descparams.Desc.SetParameter(cid, bc, new DescID(new DescLevel(C4dApi.ID_TAGPROPERTIES))))
            {
                return(true);
            }


            //////////////////////////////////////////////////////////////////////////////////////
            // Create a string value named TheName on the "Base" tab's main level
            cid = new DescID(new DescLevel(GENERAL_TAG_THENAME, C4dApi.DTYPE_LONG, 0)); // The ID of the radius value (GENERAL_TAG_THENAME)
            bc  = C4dApi.GetCustomDataTypeDefault(C4dApi.DTYPE_STRING);                 // The type of the radius value (STRING)
            bc.SetString(C4dApi.DESC_NAME, "TheString");                                // The user interface name (TheName)
            bc.SetString(C4dApi.DESC_DEFAULT, "Worscht");                               // The default value (Worscht, but overridden to Horst in the Init method)
            if (!descparams.Desc.SetParameter(cid, bc, new DescID(new DescLevel(C4dApi.ID_TAGPROPERTIES))))
            {
                return(true);
            }



            /*
             * /////////////////////////////////////////////////////////////////////////////////////
             * // Create an entirely new Tab (called "Ein schöner Tab")
             * DescID cid = new DescID(new DescLevel(CIRCLEOBJECT_NEWTAB, C4dApi.DTYPE_GROUP, 0));
             * BaseContainer bcMaingroup = C4dApi.GetCustomDataTypeDefault(C4dApi.DTYPE_GROUP);
             * bcMaingroup.SetString(C4dApi.DESC_NAME, "Ein schöner Tab");
             * // Create the new Group on the top level (DecLevel(0))
             * if (!descparams.Desc.SetParameter(cid, bcMaingroup, new DescID(new DescLevel(0))))
             *  return true;
             *
             * /////////////////////////////////////////////////////////////////////////////////////
             * // Create an new sub group (called "Hübsches Grüppchen")
             * cid = new DescID(new DescLevel(CIRCLEOBJECT_SUBGROUP, C4dApi.DTYPE_GROUP, 0));
             * BaseContainer bcSubgroup = C4dApi.GetCustomDataTypeDefault(C4dApi.DTYPE_GROUP);
             * bcSubgroup.SetString(C4dApi.DESC_NAME, "Hübsches Grüppchen");
             * // Create the sub group on the "Ein schöner Tab" main tab (CIRCLEOBJECT_NEWTAB)
             * if (!descparams.Desc.SetParameter(cid, bcSubgroup, new DescID(new DescLevel(CIRCLEOBJECT_NEWTAB))))
             *  return true;
             *
             * /////////////////////////////////////////////////////////////////////////////////////
             * // Create an new boolean value (as a checkbox) called "Check mich"
             * cid = new DescID(new DescLevel(CIRCLEOBJECT_CHECKME, C4dApi.DTYPE_BOOL, 0));
             * BaseContainer bcCheckMich = C4dApi.GetCustomDataTypeDefault(C4dApi.DTYPE_BOOL);
             * bcCheckMich.SetString(C4dApi.DESC_NAME, "Check mich");
             * bcCheckMich.SetBool(C4dApi.DESC_DEFAULT, true);
             * // Create the boolean check box under the previously created sub group (CIRCLEOBJECT_SUBGROUP)
             * if (!descparams.Desc.SetParameter(cid, bcCheckMich, new DescID(new DescLevel(CIRCLEOBJECT_SUBGROUP))))
             *  return true;
             */

            descparams.Flags |= DESCFLAGS_DESC.DESCFLAGS_DESC_LOADED;

            return(true); // base.GetDDescription(node, descparams);
        }
Beispiel #3
0
        /// <summary>

        /// This method tries to make the best out of C4Ds seldom relationship between objects with
        /// multiple materials which can or can not be restricted to polygon selections and one or more UV sets.
        /// But there are unhandled cases:
        /// Multple UV tags are not supported. Overlapping polygon selections are probably handled differently.
        /// The awkward side effects when changing the tags' order in C4D are not reproduced.
        /// </summary>
        /// <param name="ob"></param>
        /// <param name="snc"></param>


        private void VisitObject(BaseObject ob, SceneNodeContainer snc)
        {
            Collection <TextureTag>           textureTags   = new Collection <TextureTag>();
            Dictionary <string, SelectionTag> selectionTags = new Dictionary <string, SelectionTag>();
            UVWTag      uvwTag    = null;
            CAWeightTag weightTag = null;

            // SCRATCH
            // var targetComponent = new TargetComponent {ExtraInfo = aStr, Radius = anInt};
            // snc.AddComponent(targetComponent);

            // Iterate over the object's tags
            for (BaseTag tag = ob.GetFirstTag(); tag != null; tag = tag.GetNext())
            {
                // GeneralTag
                if (1036156 == tag.GetTypeC4D())
                {
                    var    di    = tag.GetDataInstance();
                    int    anInt = di.GetInt32(10000);
                    string aStr  = di.GetString(10001);
                    Logger.Debug("Found a GeneralTag with TheInt=" + anInt + " and TheString = \"" + aStr + "\"");
                    // var targetComponent = new TargetComponent {ExtraInfo = aStr, Radius = anInt};
                    // snc.AddComponent(targetComponent);
                }

                // CAWeightTag - Save data to create the weight list later
                CAWeightTag wTag = tag as CAWeightTag;
                if (wTag != null)
                {
                    weightTag = wTag;
                    continue;
                }

                // TextureTag (Material - there might be more than one)
                TextureTag tex = tag as TextureTag;
                if (tex != null)
                {
                    textureTags.Add(tex);
                    continue;
                }
                // UVWTag - the texutre coordinates. We handle only one
                UVWTag uvw = tag as UVWTag;
                if (uvw != null)
                {
                    if (uvwTag == null)
                    {
                        uvwTag = uvw;
                    }
                    else
                    {
                        Logger.Error("Object " + ob.GetName() + " contains more than one uv-coordinates-tag. Cannot handle this. Only the first texture tag will be recognized.");
                    }
                    continue;
                }
                // Selection tag. Only recognize the polygon selections as they might be referenced in a TextureTag
                SelectionTag selection  = tag as SelectionTag;
                string       selTagName = tag.GetName();
                if (selection != null && selection.GetTypeC4D() == C4dApi.Tpolygonselection && !string.IsNullOrEmpty(selTagName))    // One Type and three TypeIDs - You C4D programmer guys really suck
                {
                    selectionTags[selTagName] = selection;
                }
                // XPresso Tags - TBD
                XPressoTag xPresso = tag as XPressoTag;
                if (xPresso != null)
                {
                    // Handle XPresso tag
                    continue;
                }
            }

            TextureTag lastUnselectedTag = null;
            Collection <KeyValuePair <SelectionTag, TextureTag> > texSelList = new Collection <KeyValuePair <SelectionTag, TextureTag> >(); // Abused KeyValuePair. Should have been Pair...

            // Now iterate over the textureTags
            foreach (TextureTag texture in textureTags)
            {
                string selRef = "";
                using (BaseContainer texData = texture.GetData())
                {
                    selRef = texData.GetString(C4dApi.TEXTURETAG_RESTRICTION);
                }
                if (string.IsNullOrEmpty(selRef))
                {
                    // This material is not restricted to any polygon selection
                    lastUnselectedTag = texture;
                }
                else
                {
                    SelectionTag sel;
                    if (selectionTags.TryGetValue(selRef, out sel))
                    {
                        texSelList.Add(new KeyValuePair <SelectionTag, TextureTag>(sel, texture));
                    }
                }
            }

            // At this point we have the last texture tag not restricted to a seletion. This will become the Material of this FuseeObjectContainer
            // no matter if this object contains geometry or not
            if (lastUnselectedTag != null)
            {
                AddComponent(snc, GetMaterial(lastUnselectedTag));
            }

            // Further processing only needs to take place if the object contains any geometry at all.
            PolygonObject polyOb = ob as PolygonObject;

            // Check whether the object contains an unpolygonized mesh
            if (polyOb == null)
            {
                polyOb = ob.GetCache(null) as PolygonObject;
            }

            if (polyOb != null)
            {
                float3[] normalOb = polyOb.CreatePhongNormals();

                // Initialize the polygon index set
                int           nPolys   = polyOb.GetPolygonCount();
                HashSet <int> polyInxs = new HashSet <int>();
                for (int i = 0; i < nPolys; i++)
                {
                    polyInxs.Add(i);
                }

                foreach (KeyValuePair <SelectionTag, TextureTag> texSelItem in texSelList)
                {
                    HashSet <int> polyInxsSubset = new HashSet <int>();
                    BaseSelect    bs             = texSelItem.Key.GetBaseSelect();
                    int           nSegments      = bs.GetSegments();
                    for (int iSeg = 0; iSeg < nSegments; iSeg++)
                    {
                        int from = bs.GetRangeA(iSeg);
                        int to   = bs.GetRangeB(iSeg);
                        for (int iSel = from; iSel <= to; iSel++)
                        {
                            polyInxs.Remove(iSel);
                            polyInxsSubset.Add(iSel);
                        }
                    }

                    // Now generate Polygons for this subset
                    if (polyInxsSubset.Count > 0)
                    {
                        if (snc.Children == null)
                        {
                            snc.Children = new List <SceneNodeContainer>();
                        }

                        SceneNodeContainer subSnc = new SceneNodeContainer();

                        AddComponent(subSnc, new TransformComponent()
                        {
                            Translation = new float3(0, 0, 0),
                            Rotation    = new float3(0, 0, 0),
                            Scale       = new float3(1, 1, 1)
                        });

                        AddComponent(subSnc, GetMaterial(texSelItem.Value));
                        subSnc.Name = snc.Name + "_" + texSelItem.Key.GetName();
                        AddComponent(subSnc, GetMesh(polyOb, normalOb, uvwTag, polyInxsSubset));
                        _weightManager.AddWeightData(subSnc, polyOb, weightTag, polyInxsSubset);

                        snc.Children.Add(subSnc);
                    }
                }

                // The remaining polygons directly go into the original mesh

                AddComponent(snc, GetMesh(polyOb, normalOb, uvwTag, polyInxs));
                _weightManager.AddWeightData(snc, polyOb, weightTag, polyInxs);
            }
            else if (ob.GetTypeC4D() == C4dApi.Olight)
            {
                using (BaseContainer lightData = ob.GetData())
                    // Just for debugging purposes
                    for (int i = 0, id = 0; -1 != (id = lightData.GetIndexId(i)); i++)
                    {
                        if (lightData.GetTypeC4D(id) == C4dApi.DA_LONG)
                        {
                            int iii = lightData.GetInt32(id);
                        }
                        if (lightData.GetTypeC4D(id) == C4dApi.DA_REAL)
                        {
                            double d = lightData.GetFloat(id);
                        }
                        else if (lightData.GetTypeC4D(id) == C4dApi.DA_VECTOR)
                        {
                            double3 v = lightData.GetVector(id);
                        }
                    }
                ;
            }
        }