Modelling for XNA with Blender

FW:  http://www.stromcode.com/2008/03/10/modelling-for-xna-with-blender-part-i/

Modelling for XNA with Blender Part I

March 10, 2008

blender_big.jpgIn this series, we will look at using Blender to build models and assets for use in XNA games. In part I, we build a cube, apply a texture to it, and export it to fbx format.

<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> width="468" scrolling="no" height="15" frameborder="0" allowtransparency="true" hspace="0" vspace="0" marginheight="0" marginwidth="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-4918349833220447&dt=1212401972590&lmt=1212401957&prev_slotnames=5585453236&output=html&slotname=2273068045&correlator=1212401972528&url=http%3A%2F%2Fwww.stromcode.com%2F2008%2F03%2F10%2Fmodelling-for-xna-with-blender-part-i%2F&ref=http%3A%2F%2Fwww.ziggyware.com%2Fnews.php%3Frowstart%3D100&frm=0&cc=100&ga_vid=2992875446891075600.1212401973&ga_sid=1212401973&ga_hid=1559742151&flash=0&u_h=900&u_w=1440&u_ah=870&u_aw=1440&u_cd=32&u_tz=480&u_his=1&u_java=true&u_nplug=13&u_nmime=40" name="google_ads_frame">

Note: the Blender/XNA series is intended for coders who have every intention of hiring/finding an artist to build their assets, but would like to know enough about the basics to whip up some crude, textured, and animated models to use in their tests. If you would like to learn Blender in more detail, or you are an artist looking for a richer how-to document for Blender, I recommend the Introduction to Character Animation tutorial which can be found on the BlenderWiki. This series of articles covers only the bare essentials, and may be used as a companion to the previously mentioned tutorial.

When modeling for XNA you’ve got a lot of options. Since XNA readily accepts models in the fbx format, pretty much any 3D modeling package you can find is ready, right out of the box, to be used to build models for your XNA games.

With that said, you’ve got four classes of packages to choose from:

  • Top dollar software (Maya, 3DS Max)
  • “Free” versions of top dollar software (XSI Mod Tool)
  • Low budget software (Wings3D, trueSpace)
  • Free software (Blender)

Most of us with limited budgets are going to wipe the top dollar offerings right off the plate. For me, not only is the cost prohibitive, but I’m not even an artist — I’m a coder. Why would I spend thousands on software that there isn’t a chance in hell I’m ever going to figure out how to use, just so I can whip up some half-way decent models to use in my unit tests until I can pay a real artist to build me some good ones?

The “free” (note the quotes) offerings like Maya PE and Mod Tool, unfortunately, come with some severe limitations. Maya PE is not going to work because you can’t export, and Mod Tool comes with the caveat that you can’t use it for commercial works. What if your game starts turning out really good, as in, I can charge for this? You’re going to run afoul of the license.

For me, personally, the low budget offerings would be fine, except for one small factor: there is a full-featured, awesome piece of open source software that blows them out of the water, and with a total price of free. No cost, no restrictions on what you can do with your creations. And a positively huge community of helpful users. C’mon, there really isn’t any better alternative. That software, of course, is Blender.

Now, you might have heard some bad things about Blender. Actually, you’ve probably only heard one bad thing among all the good things people have to say about it. And that one thing is, the interface stinks! I’m going to be the odd one out. I’ve used a lot of 3D modeling software in my time,and I haven’t been able to figure out any of it. It simply doesn’t make sense to me. Blender, however, immediately made sense to me. I don’t know why, but something just clicked when I was using it the first time.
Again, I’m a programmer, not an artist, but wow are these programs complicated. When I’m building something for a game, all I want to do is build up my model, texture it, maybe add some bones to it and animate it. Right? So why is it so hard to accomplish such a simple task? The answer is that most modeling software wasn’t designed for you to build animated models for XNA. It was designed to do everything, it just so happens to be capable of building animated models for XNA. Your task is to navigate through all the options you don’t need to get to the stuff you do. Luckily, Blender seems to make finding all that other stuff kind of complicated, which is great for me, because I don’t know what any of it is. Everything I need is right in front of me, which cuts down on my anxiety. That’s a really good thing.

We’re going to go through four stages of modeling using Blender for XNA. We’ll look at:

  1. How to build a textured cube
  2. How to build a UV textured model
  3. How to add bones to a model
  4. How to animate a model

That’s pretty much all you need to know to use Blender for your XNA project. In fact, you only need 1 & 2 if you just want to build furniture, vehicles, weapons, and so on for your game. We really only need 3 and 4 to build more complicated stuff like players and NPCs.

So let’s get started. Begin by downloading the latest version of Python at http://www.python.org, and then Blender at http://www.blender.org/download/get-blender/ and install them in that order.

Note: I’ll be using Blender 2.45 for this demo. Blender seems to have this weird habit of changing things pretty dramatically between minor releases, so get your learn on while the interface still looks like I’m about to describe!

blender1.jpgNow fire up Blender. You’re presented with a default scene, which contains a cube. This is the start state for Blender, and you should see it whenever you start the program. A word of caution here: Blender’s interface was designed for efficiency, and what that means is that you will be doing almost everything using keyboard shortcuts. Good luck remembering them all!

Even though we’re going to just render a cube here, let’s delete the cube and recreate it. Hit A to select everything in the scene, and then DEL. Now hit SPACE and select Add->Mesh->Cube. We’ve got our cube back. You might have noticed a little cross hair in the middle of the window before the cube appeared. That’s the cursor, and it defines where the center of the new mesh is going to go. You could have moved that around if you wanted, but we want it in the center anyways.

So how come it doesn’t look like a cube? Because we’re looking at it square on. If you want to change your viewing perspective, hold down your MIDDLE MOUSE BUTTON and wiggle the mouse around. We’re now changing the perspective, so we can look at the cube from an angle. Looks like a cube now, doesn’t it?

So now we want to texture this thing. Let’s use the same texture we used in the Silent Hill Cube render example. You should see it off to the left. It’s a 128×128 square jpg. It could be a different size, but for a small cube like this, smaller is better. Just make sure whatever you use is a power of 2 in dimensions, i.e. either 32×32, 64×64, 128×128, 256×256, etc.

Where should you save your texture? You should save it to your XNA project’s Content folder. I like to make a subfolder called Textures and stick all my textures in there. You don’t have to, but it’s important that XNA knows where to find your texture when you build your project.

Now back to Blender. How do we wrap this texture around our cube? Well, we need to do what is called UV texturing. But we’re going to do a really, really simple version of it. In part II of this series, we’ll be tearing our model apart and actually mapping coordinates of our texture to our vertices, but since all we have here is a cube, we just want to apply the texture to each face of the cube.

blender2.jpgTo do this, we’re going to work in two separate windows. We need to split the Blender window into two separate windows. To do this, click the MIDDLE MOUSE BUTTON where the modeling window meets the menu bar at the top. A menu will pop up, so select “Split Area” and move the vertical divider to the middle of the window. LEFT CLICK to set the split. Great, now we’ve got two windows that look the same.

Underneath the right view window, you should see a little drop down that says Edit Mode. This is where you choose what mode this window is in. We actually want to be in Object Mode, so select Object Mode from this drop down.

Now we’re ready to texture. Hit F5 to bring up the shading window. You’ll see it at the bottom of the screen.

If you aren’t in the Materials buttons list, click the Materials icon (its a red ball). Click Add New. You just added a material to your mesh.

Now look on the right, and you’ll see a panel with a tab that says, Texture and one that says Map Input. In the Texture tab, click Add New. You’ve just added a texture to your material. You’ll notice that an entry named Tex appears in the list on the left.

Now select the Map Input tab. We’re going to tell Blender how to map this texture to our cube. Click the UV button. Awesome, that’s done.

Review what you just did: you created a mesh, added a material to it, added a texture to your material, and told Blender to map the texture to your mesh using UV.

Ok, now go back up to your view windows, where your cube is sitting. In the left window, change the mode to UV Face Select. We’re going to tell blender which of the faces to do the UV mapping on. We want to do it on all of them, so make sure every face is selected. The quick way to do this is to hit A.

blender3.jpgNow in the right window, change the Window Type (not the mode, the window type) to UV/Image Editor. (See the image at the left for what the window type selector looks like). The window should change to a flat square. This is your texture — well, it will be! We need to tell Blender where our texture is. So select Image->Open from the menu (the menu on this window), and navigate to your texture. Open it, and the square should now display your texture. You should also see that your cube on the left has received its texture!

blender4.jpgAgain, let’s review. After we got our cube all set up to be textured, we imported a texture and applied it to every face of our model.

Well, we sure seem to be done, don’t we? All we need to do is export our model to fbx format. On the main menu, select File->Export->Autodesk FBX. Save the fbx file to our content directory.

Are we done? Well, not quite. We still have to make sure that our XNA project can handle all of this. Add the FBX file to your content pipeline using the Add->Existing Item option in Visual Studio. Now we need to do one last thing. We need to make sure our FBX file really points to the texture. Guess what? It doesn’t. Nothing is ever easy, right?

Open the fbx file in any text editor (use vi you apes!) Search for the string RelativeFilename. There should be two instances of this line in the file, which look something like this:

  1. RelativeFilename: "fbx/mytexture.jpg"

Not good! We don’t even have a fbx folder. We need to change this line ever so slightly:

  1. RelativeFilename: "../Textures/mytexture.jpg"

And we need to do that in both places. That’s it! Now render your cube as you would any model in XNA, and you should see it all nice and textured.

Next time, we’ll look at building a more complicated mesh, and applying a more complicated texture to it. For now, here’s a neat-o video of our textured cube:

http://www.youtube.com/watch?v=BduAEENF2xw

Modelling for XNA with Blender Part II

March 11, 2008

blenderxnaii.jpgLast time we built a cube and laid a texture over it. In part II, we’ll build a more complicated mesh, unwrap it, and build a UV map to map our mesh’s vertices to a custom texture. We’ll look at some basic Blender modeling techniques along the way as well.

<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> width="468" scrolling="no" height="15" frameborder="0" allowtransparency="true" hspace="0" vspace="0" marginheight="0" marginwidth="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-4918349833220447&dt=1212402571373&lmt=1212402570&prev_slotnames=5585453236&output=html&slotname=2273068045&correlator=1212402570897&url=http%3A%2F%2Fwww.stromcode.com%2F2008%2F03%2F11%2Fmodelling-for-xna-with-blender-part-ii%2F&ref=http%3A%2F%2Fwww.stromcode.com%2Fcategory%2Fxna%2F&frm=0&cc=100&ga_vid=2992875446891075600.1212401973&ga_sid=1212401973&ga_hid=2026977988&ga_fc=true&flash=0&u_h=900&u_w=1440&u_ah=870&u_aw=1440&u_cd=32&u_tz=480&u_his=1&u_java=true&u_nplug=13&u_nmime=40" name="google_ads_frame">

Note: the Blender/XNA series is intended for coders who have every intention of hiring/finding an artist to build their assets, but would like to know enough about the basics to whip up some crude, textured, and animated models to use in their tests. If you would like to learn Blender in more detail, or you are an artist looking for a richer how-to document for Blender, I recommend the Introduction to Character Animation tutorial which can be found on the BlenderWiki. This series of articles covers only the bare essentials, and may be used as a companion to the previously mentioned tutorial.

If you’ve ever dug into the content folder of your favorite 3D game, you may have come across a bunch of textures. Usually these are pretty self-explanatory — stone, brick, asphalt, grass. Maybe a cloud texture that gets used on the skybox. Most of them look pretty standard, like something you might use as a tiled background on a website (assuming it’s 1993 and we still use tiled backgrounds on websites).

But then you come across a horror show. You find the character textures.

Why do I say it’s a horror show? Because they look like something out of Texas Chainsaw Massacre. Like you took a human body, skinned it, and laid the flesh out to dry.

charactertexture_samgrice.jpg
A Character Model Texture

Ok, all joking aside, that description is actually pretty accurate, and we’re going to look at what goes into building one of these textures and then wrapping it around a model. The process is called UV mapping, and it is essentially tearing apart your model so you can lay it flat over a 2D texture, and line up each vertex just so, in order to properly map a complicated texture — such as a human figure — over a basic, low poly mesh.

To begin with, we’re going to have to build something a little more complicated than a cube. This time around, we’re going to build a human head.

Now, if you go scouring the net for examples of and tutorials about modeling humans, you’re going to turn up a lot of stuff about high-res, awesome models that look photorealistic. But we’re not building CG characters for multimillion dollar movies, we’re building a game. That means we want to minimize the number of polygons that make up our mesh. That’s ok, though, because if we do it right, the texture we apply to our model, and the lighting and other effects we do in game, are totally going to sell it. The basic idea is you can get really detailed with your model, or you can get really detailed with your texture and lighting. Since performance matters for us (we’re rendering this thing on the fly, after all), we are definitely going to want to opt for the latter.

Now keep in mind, as I’ve stated before, I am not an artist. So don’t expect anything super awesome here. It’s up to you to paint really great textures for your models so they look great even though the actual meshes you apply them to are relatively simple.

headsketch.gif
Head Sketch

If you’ve ever taken a figure drawing class, you’ve probably seen the basic idea of sketching a head. It’s pretty simple. You basically start with a deformed sphere for the top of the cranium, and add a rectangle at the bottom-front for a jaw. Then you sketch in a little prism shape for the nose, and maybe add some half-discs for ears. You should start to imagine how we can easily do these things in Blender. We know how to add meshes, all we need to know how to do is tweak them, move them around, and then merge them into one shape. This should be quite easy. And we’re not going to get much more complicated than that, primarily to keep this tutorial simple, but also because its a game we’re working on, and we want to keep our models simple.

So fire up Blender and start a new scene. Select everything (A) and delete it. Let’s start with a blank canvas.

It might be useful to you to split the work area into several sections, each with their own view. Remember, to do this, click MIDDLE MOUSE BUTTON at the edge of a window, select Split Area, then drag the divider to where you need it. A good plan is to split the window into four viewports, and set one to top, one to front, one to side, and one to user. This will give us 3 set points of view, plus one we can drag around at will. You can set these on the view menu for each window. You might also want to learn the shortcuts, as well.

screen1.jpg
Blender with Four Viewports

Now add a sphere. But wait! An icosphere or a UVSphere? It doesn’t matter. Try both and see the difference. I’m using a UVSphere because The points are a little easier to work with.

Now what we want to do with this sphere is stretch it out a little bit. To do that, we are going to use a couple shortcut keys to let us do some things really quickly.

  • To get a rectangular edit tool we can use to drag-select a bunch of vertices, hit B. The use the LEFT MOUSE BUTTON to drag-select.
  • With our vertices selected, we can move them around with G.
  • With our vertices selected, we can scale them with S.
  • With our vertices selected, we can extrude them with E.

Don’t worry about extrude for now. Just select some verts, move them around and scale them until our sphere is more oblong looking. Look at the sketch of the head up there for a reference. That’s what we’re going for. Notice how its a little more of an egg shape, coming to a little bit of a point near the rear. You can grab half of the vertices and pull them back, then scale the ones at the end down to quickly approximate this.

Now what you’ve got at this point probably isn’t great. Don’t worry about it, we’re just learning. Do your best, and let’s move on.

Now we can add the rectangle we’re going to use for the jaw. But instead of just dropping in a big rectangle, we’d actually like it to taper off near the chin. The cheek bones should be wider than the chin. To achieve this, we’ll use the extrude function.

Add a very small cube near the sphere. Before you do this, you might want to reposition the cursor. Use your three perspective windows to position the center of the cube you’re going to add just under the front-bottom of your deformed sphere. Make sure your cube isn’t touching your sphere. We’re going to build this part of the head separate from the cranium, then merge the two together eventually.

Ok, we’ve got a cube, but we wanted to start with something smaller. With your cube selected, scale it down until its top face is about the right size to drop in the sphere and form the top of the jaw box.

Now, hit B and drag-select the bottom 4 vertices. Use G to move them up and flatten out the cube into a rectangle. Now we’re going to extend it back downward using the extrude tool. To use extrude, make sure those bottom 4 vertices are selected, hit E, and drag downward to extend your vertices downward. Notice that we’re making new copies of these vertices, and extending the rectangle in the process. You should begin to see how useful extrude is. You can start to rough out pretty much any shape starting from just a cube using it.

screen2.jpg
A Rough Jaw

Continue downward until our rectangle has about four segments. At each step, use the scale and move functions to make your jaw look more like a jaw. Again, see the sketch above and use it as a reference. You should go for a more trapezoidal look, flat in the front, but extending backward as you move up the backside.

Looks kind of like a jaw, right? Come on, cut me a break here. I’m doing my best.

So what we want to do know is merge this jaw structure into the egg.

Now, there are no doubt much better ways to do this. I simply don’t know them. Hopefully someone will add a comment suggesting a better way. The way I do know how to do this is to follow three steps:

  1. Remove a section of the egg where the jaw will fit in
  2. Remove the back faces of the jaw
  3. Go around the seam and merge vertices

It’s easy to delete vertices. Just select them, and hit delete. Do this for the vertices on the bottom-front quadrant of our egg. Now grab your jaw and move it in. You might find you need to remove more vertices, or you added too many. The key thing, to keep things simple, is make sure you don’t have faces overlapping. We’re going to glue everything together eventually, so for now just make things kind of close, without overlapping.

screen3.jpg
Moving the Jaw Into Place

Just keep using the tools you know about to get as close to something resembling a head as you can. Again, don’t sweat the details, just do your best.

Now we need to merge some vertices. You might want to introduce yourself to a new button at this point. On the menu bar for each view, when you are in edit mode, you’ll see, at the right, some select option buttons. These let you say if you want to select vertices, edges, or faces. There is also a button that determines if drag-selecting will select “hidden” vertices — that is, vertices that are behind the faces you see. When you want to be really specific about which vertices you want to select, it’s a good idea to turn this off. That way, you’ll only be selecting those vertices you can see. You may also want to stop using drag-select here, and start selecting individual vertices using RIGHT MOUSE BUTTON.

Ok, now let’s get merging. There are a couple tools we’re going to use to do this:

  1. With two vertices selected, we can merge them by hitting ALT-M and selecting At Center (that’s a decent enough option, but experiment).
  2. With two vertices selected, at either end of an edge, we can add a new vertex in between them by hitting W and selecting Subdivide.

The idea here is to stretch the skin of one mesh (the sphere) and glue it to the edges of the skin of another mesh (the jaw). Move around the game between the two meshes, adding vertices and merging vertices until you close them up in a good looking fashion. Inspect your model well to make sure there aren’t any weird overlaps, of holes, or anything like that. Make it smooth. As you move around the gap, remember to de-select all vertices between merge/split operations. Things can get ugly if you have vertices selected and you don’t know it.

Once you’ve closed up the gap, you can then add a nose. Just find a good edge somewhere on the center of the face and subdivide it to get two points for the tip of the nose. Then grab them and pull them out to form a nose. Tweak the vertices until it looks passable.

When you’re ready to double check everything, switch over to object mode and make sure all the holes and gaps are full again. If you find any holes, you can select three vertices and hit F to fill them in by creating a face out of them.

screen4.jpg
Our Head in Object Mode

So how did I do? Ok, that’s definitely not great, but it’s good enough for a non-artist. Definitely came out better than I have any right to.

So now we need to texture it. Recall the process of texturing a cube in part I. This is pretty much the same, except we have this extra step of unwrapping our mesh and getting really specific about which part of the texture gets mapped to which part of the mesh.

Switch to the two window mode we used last time. The window on the left should be in UV Face Select mode, and the window on the right should be a UV/Image Editor window. Only this time, we’re not going to load in a texture just yet.

Let’s let Blender unwrap the mesh and see how it does. Select all faces in the left window, and hit U then select Unwrap. One of three things is going to happen here.

  1. Nothing
  2. Your mesh will get unwrapped, but it will look like a huge mess
  3. You’ll get super lucky and it will unwrap perfectly

Disregard #3, its not likely. #1 happened to me. What do we do?

screen5.jpg
Marking a seam

W e need to tell Blender where it should slice our mesh when unwrapping. We’re basically giving it some hints about where might be a good area to cut it open. Ideally, we should do this somewhere that would be easy to hide the seam when we paint our texture. In other words, don’t do it right down the middle of the face. How about the back of the head?

The first thing I’m going to do is switch the left window back to edit mode (TAB), and hit the edge select button. Then I’m going to move along the back of the head, selecting edges to form a seam up along the base of the head, up over the top, and down to just above the brow. I then hit CTRL-E and select Mark Seam. I’ve now finalized one cut.

Now unwrap again. This time, unwrapping actually did something.

screen6.jpg
First unwrap

Unfortunately, it doesn’t look that great. That’s ok, we just need a few more cuts. You can basically keep cutting wherever seems logical for your particular model. Unfortunately, this is a really tough process and requires a lot of practice to get the hang of it. I’m nowhere near good at it, myself. But let’s see what I can do.

Keep in mind that if you make a bad cut somewhere, you can always select your edges again, hit CTRL-E and remove the seam. Another helpful thing to do is to load up a special texture file that will help you see what you’re looking at.

uv_grid_numbers.jpgThe image to the left is one you can use. Click it to view the full size. Open that texture, and you’ll better be able to visualize which parts of your mesh are mapping to what parts of the texture.

You can also select vertices on the UV map and move, rotate and scale them. Sometimes this is helpful for tweaking things and getting them to work.

For simplicity sake, I’m going to do this the braindead easy way. I’m going to cut around the face, and then along the back of the head. I won’t care much about the back of the head. I’ll primarily want the eyes and mouth to line up. The rest is details.

screen7.jpg
Second unwrap

Ok, see that there? I’ve completely failed to do this very well, but at least I can see the two sides of the face, the front of the face, and the top and back of the head. GOOD ENOUGH. Wow this part sucks.

Let’s start painting.

Blender will allow you to export this map so you can paint over it in Photoshop. To do this, switch your left window to a Scripts Window. From the scripts menu, select UV->Save UV Face Layout. Select the size you want (I stuck with 512), give it a name, and save. Now open it in your paint program and start trying to build a face. HAHA good luck.

facelayoiut_sphere.jpg
The worst head texture ever

For comedy effect, and because it’s late and I want to wrap this up, I decided to paint a totally ridiculous texture. There it is off to the left.

I wanted to show you how doing textures right can compensate for the lack of detail in your model. Instead, this texture is showing how a bad texture can highlight exactly how low-fi your model is. Two sides of the same coin, I guess. I would recommend Googling for some example character texture maps and study them. Try to understand what the artist was doing to add shading and depth to the model.

Anyways, all that’s left to do in Blender is open the texture image in the UV/Image Editor window, switch the left window to a 3D View window, in Object Mode, and switch to Textured view.

If all looks good, we can export to fbx as before, making sure the fbx actually points to our texture, and load it up in XNA.

Witness the atrocity below. It’s like Tron on acid.

screen8.jpg
Good God, we spent 3 hours on that?

It’s hideous, but it should illustrate how the UV map mapped the vertices to the texture. Look at my unwrapped model, and then look at my texture. See how the face pieces lined up to the face, the sides lined up to the side of the head, and the little ball thing mapped to the point of the egg.

With practice, you should be able to improve at getting the right level of detail in your model, and the right quality in your texture, to make your models look really great in-game.

You now know pretty much everything you need to know to build static objects for your game. As you can imagine, a chair or a couch, even a car is going to be a lot simpler than a head. Any non-animated model you need is going to be built this way. You’ll want to explore Blender a little bit to learn some of the tools available to you.

To get you started, consider adding a plane and extruding it. This will let you build a shape of your choosing out of square faces.

What if you want to make a symmetrical duplicate? One way to do this is to switch to edit mode, select your object, and hit ALT-D. This duplicates your object. To move it to a mirror position around one of the axes, hit N and set ScaleX (or Y, or Z) to -1. You should suddenly see two of your objects, reflected about the axis you chose. This will make a linked duplicate. That means its actually one mesh, so if you edit one of them, the changes will show on the other one. If you create a mirror image, this is pretty much what you want to do for, say, a head.

Explore, learn more of the keys and shortcuts.

Next time, we’ll look at adding bones to a mesh as the first step towards animating.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值